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
name::String
end
julia> f(m::MyType, i::Integer) = i + 1
f (generic function with 1 method)
julia> arr = [1,2,3]
3-element Vector{Int64}:
1
2
3
julia> my = MyType("John")
MyType("John")
julia> f.(my, arr)
ERROR: MethodError: no method matching length(::MyType)
[...]
julia> map(x-> f(my, x), arr)
3-element Vector{Int64}:
2
3
4
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?
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.