Skip to content

Operator vs pipe method #154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dfernandez79 opened this issue Jul 5, 2019 · 6 comments
Closed

Operator vs pipe method #154

dfernandez79 opened this issue Jul 5, 2019 · 6 comments

Comments

@dfernandez79
Copy link

dfernandez79 commented Jul 5, 2019

I don't know if the GitHub issues are the right place to send comments about the proposal to outsiders. Sorry if my comment is in the wrong place.

Right now I'm working in a DSL like code, and having this infix compose operator will be wonderful. However, while reading the proposal I wonder if adding a pipe function (like RxJS, also mentioned in the README) to built-in objects was considered.

let result = "hello"
  |> doubleSay
  |> capitalize
  |> exclaim;
let result = "hello".pipe(
  doubleSay,
  capitalize,
  exclaim
);

Advantages:

  • Compatibility: Doesn't require parser changes, so current tooling will work.
    It works with numbers too if you add parenthesis (today Number has some instance methods too).
  • Extensibility: Objects may be able to override the default behavior (Object.prototype already includes methods like toString, hasOwnProperty)

Disadvantage:

  • May cause issues with objects that already define a pipe method.

I'm not proposing a change, but if there are any pointers to related discussions it will be helpful to learn more (I saw discussions about a pipe function but not about a pipe method).

Many thanks

Related Discussions:
There seem to be related discussions:

Some of the comments mention that the global built-in pipe function is not as easy to read as the operator. However, "hard" or "easy" to read sometimes depends on how used you are with the syntax. For example: is hard for me to favor this style fn(a |> b |> c, x |> y |> z) over this fn(a.pipe(b,c),x.pipe(y,z));.

My observations are about compatibility and extensibility; usability will be better answer by studies like the one of #150

@noppa
Copy link
Contributor

noppa commented Jul 8, 2019

Would adding new properties to Object.prototype be considered a breaking change? I think there could quite possibly be some code out there that does something like

function doSomething(options) {
  if (options.pipe) doSomething()
  else doSomethingElse()
}
doSomething({ pipe: true })
doSomething({})  // Works now, would break if pipe-property is added to Object.prototype

Especially since the method pipe and terminology around it is used in Node.js streams.

@ljharb
Copy link
Member

ljharb commented Jul 8, 2019

Yes, but this would be to Function.prototype.

@noppa
Copy link
Contributor

noppa commented Jul 8, 2019

I don't think that's what @dfernandez79 is proposing here.

let result = "hello".pipe(
a |> b |> c ... a.pipe(b,c)

@ljharb
Copy link
Member

ljharb commented Jul 8, 2019

ah, true - then yes in that case it’s a nonstarter.

@dfernandez79
Copy link
Author

@noppa You're right, it would break compatibility. Thank you for answering.
I like the idea of the method more than the operator. One big difference between JS and functional languages like Haskell is that there is no way to define infix functions, the method was a good way to extend how things are composed in the pipe and it didn't require any parsing changes... but I guess that any change to Object.prototype will break existing code, no matter the chosen name.

@hax
Copy link
Member

hax commented Nov 29, 2019

There will be no compatibility problem if we use bind operator:

let result = "hello"::pipe(
  doubleSay,
  capitalize,
  exclaim,
);

And it seems Emitter proposal use similar pattern:

const { on, map, filter, run } = Emitter
run(
  on(document, 'click'),
  filter(ev => ev.target.tagName === 'BUTTON'),
  map(ev => ({ x: ev.clientX, y: ev.clientY })),
  coords => console.log(coords),
)

Note run allow the subject to be the first argument.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants