Marking types as scalar for broadcasting, Ref vs. Tuple?

The typical method of marking a type as scalar for broadcasting seems to be

Base.Broadcast.broadcastable(x::MyType) = Ref(x)

I’ve experimented a bit with

Base.Broadcast.broadcastable(x::MyType) = (x,)

as an alternative, to avoid allocation of the Ref (or is that always elided?). Seems to work fine, but I wonder - is there any downside to using a Tuple here that I just haven’t run into yet?

Quoting Matt from https://discourse.julialang.org/t/recent-broadcast-changes-iterate-by-default-scalar-struct-and/11178/12:

You can also use a tuple literal like @. f(x, (y,)) to treat y kind-of like a scalar. For most purposes this should be just as fast and scalar-like as a Ref , but it’s not 100% scalar-like: if x is scalar-like or a zero-dimensional array, f.(x, Ref(y)) will return an unwrapped scalar, whereas f.(x, (y,)) will return a 1-tuple. Some array types might also not support broadcasting with tuples as nicely as they do scalars.

So you can compare e.g.

julia> f(x, y) = x + y;

julia> f.(1, Ref(2))
3

julia> f.(1, (2,))
(3,)
4 Likes

Thanks, @fredrikekre!