I’m starting to come around on the double underscore, although it would be nice if it was a symbol that’s easier to distinguish from a single underscore.
@tkf, I think ys |> Iterators.product(xs, __, zs)
is a reasonable example. Eventually (or regularly), someone is going to want to pipe into a middle argument, and then they would be disappointed when they found out that |>
and |>>
won’t do the trick.
I can see your point here. Currently in base Julia, and with your @_
macro, anything to the right of a pipe must evaluate to a unary function. However, with the updated |>
and |>>
pipes, if you try to evaluate an expression to the right of a pipe on its own, you’ll end up calling a method of your function with one less argument than the method invoked by the pipe. That doesn’t necessarily make the syntax wrong, but it does seem conceptually less satisfying.
On the other hand, I’m not sure your example is too convincing. If I wanted to pull out part of a pipe and create a named function for later re-use, then I would probably just use normal function syntax:
f(x) = @_ filter(_.age > 27, x)
s(x) = @_ sort(x, by = _.height)
pipeline = s ∘ f
Or I could still use the updated-syntax pipes if I wanted to:
f(x) = x |>> filter(y -> y.age > 27)
s(x) = x |> sort(by = y -> y.height)
A minor quibble: It’s cool that @_
and @>
work together, but @_ @> 10 foo(_, 1) foo(_, 2)
is a bit more complicated than just using @>
by itself:
julia> foo(x, i) = (println("foo(_,$i)"); x)
foo (generic function with 1 method)
julia> @> 10 foo(1) foo(2)
foo(_,1)
foo(_,2)
10
Back to the double underscore. I do appreciate the way it marks which argument is being piped into, and that you can use it to pipe into any argument. But since this is a macro, for visual clarity would you consider using ~
instead of the double underscore? Here’s an example to look at:
table = [
(age=45, height=180),
(age=32, height=170),
(age=55, height=175)
]
@_ table |>
filter(_.age < 50, ~) |>
sort(~, by=_.height) |>
first |>
~.age