I think the infix syntax is a bit of a distraction here. If you define a new function:
julia> function pipe(x, f)
x |> f
end
pipe (generic function with 1 method)
then I hope you’ll agree that:
(3, 4) .|> ms1
should be equivalent to:
pipe.((3, 4), ms1)
When written without the |> infix, I think it becomes more obvious why this doesn’t work: you are broadcasting over both the input (3, 4) and your struct ms1 itself. Julia doesn’t know how to iterate over a MyStruct, so this broadcast fails.
Wrapping ms1 in a 1-element tuple fixes the issue because you are now broadcasting over that tuple, which works just fine. Ref(ms1) would also work, and is a bit more idiomatic in Julia.
You can tell Julia to treat your struct as a scalar in broadcasting operations with:
Base.broadcastable(s::MyStruct) = Ref(s)
at which point all of your examples should now work as intended:
julia> (3,4) .|> ms1
(6, 8)