-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Add support for a pipeline operator |> #2585
Comments
I'm cautiously optimistic about this direction. I don't think this is something we should push for in Carbon 0.1, but it seems like an interesting avenue to explore post-0.1.
#1122 (extension methods) could help here, but isn't really great, because you only get to pick one parameter to be We could also allow functions to be treated as methods, with the
... but I don't find this syntax especially aesthetically pleasing, and it would be a special case rather than a natural consequence of our other rules.
The |
If we do decide to implement this feature, a nice mental model for this is an analogy to a calculator. |
For the benefit of other readers: |
less symbol more readable |
Some thoughts: is this just syntactic sugar, or a lead into FP? data Polygon = Poly
scale :: double -> Polygon -> Polygon
scale s p = undefined
rotate :: Double -> Polygon -> Polygon
rotate a p = undefined
translate :: Double -> Double -> Polygon -> Polygon
translate x y p = undefined
{-
transformed_polygon: auto = polygon
|> scale(5.0)
|> rotate(90.0)
|> translate(3.0, 5.0);
-}
-- either with composition
x1 = ((translate 3.0 5.0) . (rotate 90.0) . (scale 5.0)) Poly
-- or with right associative application
x2 = translate 3.0 5.0 $ rotate 90.0 $ scale 5.0 $ Poly There are some inconsistencies that should be addressed
let x1 : auto = polygon |> scale(%, 1.2);
let x2 : auto = polygon |> fn (p){ return scale(p, 1.2)}; // some lambda instead of a function
let lambda = fn (p){ return scale(p, 1.2)};
let x3 : auto = polygon |> lambda
fn getlambda() -> auto {return fn (p){ return scale(p, 1.2)};}
let x4 : auto = polygon |> getlambda();
fn getpartial() -> auto {return scale(%, 1.2)};
let x5 : auto = polygon |> getpartial(); We also have some potential for ambiguity in this case:
// if "." is relaxed such that a.f is applies function f with a as first argument, then we need no more
// some struct with private internals
let x : PrivStruct
fn foo(y: Polygon) -> PrivStruct
fn bar(p: PrivStruct, x: i32) -> PrivStruct
polygon. scale(0.3).foo().privStructMethod(3).bar(4)
let trans : auto = scale(%, 0.5) => rotate(%, 90) => translate(%, 3, 2);
polygon |> trans |> printMe
let x: auto = [1,2,3,4]
let y: auto = [polygon.clone() for _ in 0..x.len()]
zip(y,x).map(scale) |> printMe |
Summary of issue:
Support a pipeline operator
|>
to pass the output of one function as parameters to another function,This is a feature that exists in many languages, And it can improve code readability.
Details:
Examples
Say we have some functions:
Now compare the difference in readability between the following two code examples:
I think most would agree that the first option is more readable.
Another example is with iteration (loosely):
The alternatives aren't great
Notice that if the above functions can be declared as methods of
Polygon
, then the above can be expressed in terms of chaining methods:however this is not always appropriate to define functions as methods of classes.
Another way to solve this is with temporary values, the output of each function is saved in a temporary value and pass that value to the next function
This too is not great.
Alternative syntax
We can have a symbol such as
%
that will be placed where arguments are normally passed to a function, this has the advantage of being able to specify to which argument of next function will the output of the previous function go:Passing the components of a tuple as arguments to a function
Sometimes functions return multiple values as a tuple, It may be desirable to pass those multiple values as arguments to the next function, if so there needs to be a way to differentiate between passing the tuple and passing its components, perhaps with an operator
||>
or|>>
or something similar, or perhaps unpacking tuples can be solved by some other mechanism of the language, or if we go with the option of the%
symbol perhaps we can use the following syntax:or perhaps this syntax:
Other languages
and obviously shell languages have a similar concept:
and many others...
Any other information that you want to share?
No response
The text was updated successfully, but these errors were encountered: