Defining custom pipe operator


#1

Hello! I’m trying to define a pipe operator which propagates nothing. It sounds quite easy: ⇒(x, f) = x == nothing ? nothing : f(x). This operator works fine when there is a single application of it, e.g. [1, 2, 3] ⇒ collect. However, multiple consequtive applications are called “backwards”: [1, 2, 3] ⇒ collect ⇒ length tries to call length(collect) first, and throws an error of course. Is there a way to modify this behaviour and call operator from left to right?


#2
⇒(x, f) = x == nothing ? nothing : f(x)
⇒(g::Function, f) = g ∘ f
[1, 2, 3] ⇒ collect ⇒ length # returns 3

#3

It kinda-works, but not always. First, you have a typo - it should be f \circ g, not the other way. Also compare this: sin |> typeof gives typeof(sin), while sin ⇒ typeof gives #52 (generic function with 1 method). However, for most cases I guess this should be ok…


#4

A worse problem is that nothings that are output by f are not propagated at all. I need to think about this a bit more.


#5

It is not possible to change the left/right associativity of operators programmatically since that happens at the parser level.


#6

This should work, as long as the first input, x, is not a function.

⇒(x, f) = x == nothing ? nothing : f(x)
⇒(f::Function, g) = x -> ((x ⇒ f) ⇒ g)

#7

Consider using the existing |> operator.

julia> [1, 2, 3] |> collect |> length
3

#8

But aren’t there any other predefined operators with the associativity needed here? I hoped that arrows are treated the same as |>, but apparently not.


#9

The whole point is to make an operator similar to |>, which propagates nothings. Of course, I could overload |> itself, but this doesn’t look right.


#10

All of the * and + like operators are left-associative, for example, which is what you want. For example, you could use (tab-complete \triangleright).


#11

Oh, thank you! It’s not really intutinve how to get the associativity of all those unicode operators.