Why Julia doesn't consider maximum function in the chained functions when combining anonymous function?
Asked Answered
H

1

6

I've just got aware of chaining functions (like a pipeline) in Julia for a couple of days. I was trying something today and got an unexpected result. Hence, I decided to ask about the root of the problem better to understand the behavior of Julia in chaining functions. Consider this example:

julia> a = [1 2 3]
1×3 Matrix{Int64}:
 1  2  3

Then I want to chain some functions like the below, and after all, I want the maximum value of the entire Matrix:

julia> a .|> x->x^2 .|> sqrt .|> Int64 |> maximum
1×3 Matrix{Int64}:
 1  2  3

But I expected just a 3! Why doesn't Julia consider that last function of the chain, namely, the maximum function?

PS: Also, I tried this way:

julia> a .|> x->x^2 .|> sqrt .|> Int64 |> x->maximum(x)
1×3 Matrix{Int64}:
 1  2  3

Still not what I expected it to be.

Honna answered 13/7, 2022 at 16:16 Comment(0)
H
4

The problem is actually the arrow operator not the pipe! The pipes are fine.

Remember, you can always use the colon operator if you want to examine the parsing order:

julia> :(a .|> x->x^2 .|> sqrt .|> Int64 |> maximum)
:(a .|> (x->begin
              #= REPL[84]:1 =#
              ((x ^ 2 .|> sqrt) .|> Int64) |> maximum
          end))

The arrow first evaluates everything on the right, then pipes the result from the left (right associative), so what you have is the same as:

a .|> x->(x^2 .|> sqrt .|> Int64 |> maximum)

On the right you just create a function that pipes the argument (a single number in our example) all the way to maximum, and the mapping just does it 3 times giving you the result.

What you want is:

a .|> (x->x^2) .|> sqrt .|> Int64 |> maximum

I would generally make sure the arrow is wrapped in parenthesis wherever you use it together with pipes - it is very counter-intuitive otherwise!.

If you would have just done something like

a .|> sqrt |> maximum

you would have not noticed this. Note the associativity of piping makes perfect sense - the above is

maximum(sqrt.(a))

as you would expect. The thing about the right arrow function, is that it cannot really "know" what is supposed to be the function on the right, so it just parses everything.

Haemostatic answered 13/7, 2022 at 16:39 Comment(2)
I suggest that adding output of :(a .|> x->x^2 .|> sqrt .|> Int64 |> maximum) to the answer would make it clear how this expression is parsed by Julia. Thank you!Detain
I don't know why my comment got removed. Anyway, Thank you both, @BogumiłKamiński and kabanus. It's a great and complete answer to my question, and now I fully understand what was happening in my chained functions.Honna

© 2022 - 2024 — McMap. All rights reserved.