When to use broadcasting with . vs map

That’s because broadcast is special cased for tuples to call map: @inline broadcast(f, t::NTuple{N,Any}, ts::Vararg{NTuple{N,Any}}) where {N} = map(f, t, ts...). In the general case, it really is just broadcast(f::Tf, As...) where {Tf} = materialize(broadcasted(f, As...)), which I suppose dot syntax always lowers to.

I don’t think the accepted comment about collect being the source of worse performance would apply to tuples, it appears that collect occurs in the fallback broadcastable(x) = collect(x), but tuples are one of the many types where broadcastable returns the input. Not sure exactly where in the broadcast machinery is the source of worse performance than map.

Ahh right was wondering why that example wasn’t as bad as I thought. It’s a little confusing that . and broadcast are not actually the same.

It seems like having >3 distinct types in the tuple triggers some heuristic and demotes the return type to NTuple{N, Any}.

1 Like

Sounds similar to the Union-splitting limit, but I’m not sure because inferring up to 3-4 types in a Union is not at all the same as inferring a tuple of 3-4 types in any number or order, that’s way more than 3-4 tuple types.