Is it possible to define broadcasting behavior for a type without having to define Base.length
?
Yeah. One way woudl be to just overload Base.broadcasted
:
julia> struct MyVector{T}
data::Vector{T}
end
julia> v = MyVector([1,2,3])
MyVector{Int64}([1, 2, 3])
julia> Base.broadcasted(f, v::MyVector, args...) = Base.broadcasted(f, v.data, args...)
julia> exp.(v .+ 1)
3-element Vector{Float64}:
7.38905609893065
20.085536923187668
54.598150033144236
julia> length(v)
ERROR: MethodError: no method matching length(::MyVector{Int64})
A more robust way would be to define a custom broadcast style as explained here: https://docs.julialang.org/en/v1/manual/interfaces/#man-interfaces-broadcasting
Unfortunately, the docs on custom broadcast styles are kinda lacking in examples that aren't basically just standard arrays.
Actually, the easiest thing here would probably be to use Base.broadcastable
instead. So instead of defining broadcasted
above, you'd just do
julia> struct MyVector{T}
data::Vector{T}
end
julia> v = MyVector([1,2,3])
MyVector{Int64}([1, 2, 3])
julia> Base.broadcastable(v::MyVector) = v.data
julia> log.(1 .+ 3 .+ v)
3-element Vector{Float64}:
1.6094379124341003
1.791759469228055
1.9459101490553132
Maybe now it's time for someone to answer this really old SO question of mine?
Upvoted :+1:
Thank you @Mason Protter and everyone else. I will read the links to learn more about custom broadcasts.
It would be nice if someone with more experience in custom broadcasting styles could write a blog post for the community. This is a topic that Julia can really shine and yet very few of us understand it well even after years playing with the language.
Last updated: Nov 06 2024 at 04:40 UTC