I’m running into something really strange for me in a pipeline. Can someone please explain why these two produce different results?
julia> "0X" |> x -> collect(UInt8, x) .|> x -> x == UInt8('X') ? UInt8(':') : x .|> x -> x - UInt8('0')
2-element Vector{UInt8}:
0x00
0x3a
julia> ("0X" |> x -> collect(UInt8, x) .|> x -> x == UInt8('X') ? UInt8(':') : x ) .|> x -> x - UInt8('0')
2-element Vector{UInt8}:
0x00
0x0a
All I did differently was add parenthesis in the second one and then it magically “works”. But to me the first one should “work” too, but it doesn’t. What’s happening and what should I keep in mind so I don’t get bit by this again?
You’re just confused by precedence of operators, try to run one pipe at a time and see when parentheses made a difference, and then you will figure out which operator has the precedence you didn’t expect
Thank you for your help, @jling. That is really confusing. I would expect pipes to work the same way as in bash. If you do some stuff | other stuff you almost always get (some stuff) | (other stuff). some (stuff | other) stuff doesn’t make any sense. Why would julia not make the pipes parse last?
Bash doesn’t have anonymous functions, which is where things are breaking down.
Because you can pipe inside functions too, and if that’s not what you intend, you should use some syntax to delineate where an anonymous function starts and ends. Bash has {} for that, here you can use parentheses. Anonymous functions also have the function block syntax with end, though 1-liners need a newline semicolon if you’re returning an expression inside parentheses or brackets e.g. function (x); (x,) end.
julia> "0X" |> (x -> collect(UInt8, x)) .|> (x -> x == UInt8('X') ? UInt8(':') : x) .|> (x -> x - UInt8('0'))
2-element Vector{UInt8}:
0x00
0x0a
julia> "0X" |> function (x) collect(UInt8, x) end .|> function (x) x == UInt8('X') ? UInt8(':') : x end .|> function (x) x - UInt8('0') end
2-element Vector{UInt8}:
0x00
0x0a