I have experienced this problem a lot and it’s beyond frustrating. For some reason any dot syntax call that includes a
struct fails. I can use
map but is it possible to use dot syntax here? What am I missing?
julia> struct MyType
julia> f(m::MyType, i::Integer) = i + 1
f (generic function with 1 method)
julia> arr = [1,2,3]
julia> my = MyType("John")
julia> f.(my, arr)
ERROR: MethodError: no method matching length(::MyType)
julia> map(x-> f(my, x), arr)
broadcasting treats things as vectors by default. If you want broadcasting to treat
MyType as a scalar, define
Base.broadcastable(x::MyType) = Ref(x)
Wow, thanks - what a great trick. Is there a reason not to use this line in every single type definition? Would I be breaking anything by overriding
broadcastable like this?
no, this is what you should do, broadcast is an interface:
this is not overriding, nor hack, because you own the type, and you need to teach Julia what to do with your types during broadcasting. Another similar concept is number type promotion
Could be made default with
Base.broadcastable(x::Any) = Ref(x), and only overridden explicitly for objects that can be broadcast such as tuples, arrays and matrices. Why not do things this way?
So that is how it works for
Numbers. The reason for the decision is that there were deemed to be more collection-like objects rather than scalar-like non-number objects. This is a very subjective decision obviously, and either way, someone needs to change the behavior for their type. Note that if you are defining a lot of similar scalar-like types, you can define
broadcastable on a common super-type to give all subtypes that behavior.
People wanted to remove this behavior from numbers make numbers non-iterable? · Issue #7903 · JuliaLang/julia · GitHub but it was too much work at the time, and now it’s too late. I wouldn’t suggest adding collection semantics to other arbitrary types that aren’t actually collections.