-
Notifications
You must be signed in to change notification settings - Fork 428
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
Feature: Using dot operator instead of pipe operator #1638
Comments
https://github.com/tc39/proposal-pipeline-operator It seems different things |
@OlegLustenko Yes, they are different things. But as as the dot has no meaning in the context of Tuples, List and only the meaning of accessing properties in records, I thought, you could maybe extend the meaning of the dot operator. In some sense, the pipeline operator and methods in a OOP language, are similar. Consider the following javascript class. class Point {
constructor(x, y) {
this.x;
this.y;
}
add(point) {
return new Point(this.x + x, this.y + y);
}
distance() {
return this.x**2 + this.y**2;
}
} I don't need to put the methods point1.add(point2).distance() In reason, I can write the code like this: type point = {x:int, y:int};
let add = (p1: point, p2: point) => {
let x = p1.x + p2.x;
let y = p1.y + p2.y;
{x,y};
};
let distance = (point: point) => {
point.x*point.x + point.y*point.y;
}; Similarly, as in javascript, I can chain things, but even more powerfully, with the pipe operator: point1 |> add(point2) |> distance; That is why I think the pipe operator, and methods access in OOP are similar. In my proposal, you would write it like this: point1.add(point2).distance |
I'm not sure this would make it easier for js devs. The pipe operator is very different from method chaining. |
It seems like D, Rust and Nim have something similar:
The difference between methods and functions is that the Syntactically, there is a big difference, the main downside of the function syntax is that functions can not be easily chained. The pipeline operator solve this syntax issue. My proposal is to go even further, and make no syntactical difference at all. As D, Rust and Nim also seem to do. |
@kasperpeulen are you proposing that we change the record access syntax? What would the new syntax be for "I want the bar attribute of the foo record"? (currently The "pipe dot" proposal, on the other hand, could be implemented without any other fallout. One reason Rust is able to do what it does is that its inference engine is much more restricted -- you have to annotate each function signature (as opposed to Reason, where very little must be annotated). |
@jaredly Yes I would say that then This may indeed give significant compiler work. I guess you are right about it being a better match for Rust. I think you would need function overloading for this to make real sense. And annotating your function parameters. Also, from a javascript background, Im used to importing functions. Talking to people on discord, it seems like in Reason people prefer writing: In that way, my proposal would become messy and less reasable: So Im not so sure myself anymore if this proposal would make sense for Reason. But I let you guys to decide. |
Thanks for contributing to the discussion, regardless! |
I do think of myList |> List.map(fn) Could be written as: myList . List.map(fn) And the parallels between FP and OO become very clear. In fact, a dot with spaces around it isn't even ambiguous with record field access so we could in theory add such a syntax for As you pointed out the one thing that would really make this analogy to OO patterns would be the existence of Haskell style "type classes", but even without that - it's still a cool idea. Unfortunately, we cannot remove the spaces around the myList.List.map(fn) It means " |
I think I might vote for |
Yeah, I was thinking the same thing. 😄 |
We now have |
Consider the following example:
Coming from Javascript, this may look very foreign. However, if we would introduce the dot (
.
) operator, to mean the same as the pipe operator, then this would look like this.This is almost exactly how it looks in javascript. Another adventage is that you only have one character to type.
I'm just learning Reason, so I probably don't really oversee what the consequences would be for introducing this syntax.
One challenge that I see. Say you have a record:
let record = {foo: "foo", bar: "bar"}
and there is also a functionfoo
available in the same scope, where the type of record is the last parameter.What happens, if you do
record.foo
? I guess it makes most sense (and non-breaking) if the properties of the record have higher priority. If you would want to use the functionfoo
act onrecord
, you should cast the functionfoo
to a different name.One other thing that feels strange to me (as Javascript programmer), is that the pipe operator takes the last argument. I understand that this most natural in the context of auto currying, and defining
x |> f
, to bef(x)
but if I would make my own API of functions acting on some typemyType
, I would most naturally put, putmyType
as first parameter.The text was updated successfully, but these errors were encountered: