For two objects A
and B
we could previously get the vector [A*A, A*B]
with the code A .* [A, B]
. From the deprecation warnings in Julia 0.7, it seems that the new way to do this is to use a reference of the first A. So it becomes Ref(A) .* [A,B]
.
It doesn't seem that there is a strong link between references and broadcasting operations. What is the link here and why is using a Reference preferred (by the deprecation warnings at least)?
import Base.*
struct example
num::Int
end
function *(lhs::example, rhs::example)
return example(lhs.num * rhs.num)
end
A = example(2)
B = example(4)
# Previously this could be done as follows.
A .* [A, B]
# Now we need to use Refs
Ref(A) .* [A, B]
I will here refer to the main case of Ref
, that is when you pass it one argument (there are also other subtypes of Ref
but they are not relevant for us here).
Writing Ref(x)
creates a mutable wrapper around object x
. The wrapper is a very simple RefValue
type defined in the following way:
mutable struct RefValue{T} <: Ref{T}
x::T
RefValue{T}() where {T} = new()
RefValue{T}(x) where {T} = new(x)
end
Now why it is useful, because Ref
has defined the following utility functions:
eltype(x::Type{<:Ref{T}}) where {T} = @isdefined(T) ? T : Any
size(x::Ref) = ()
axes(x::Ref) = ()
length(x::Ref) = 1
ndims(x::Ref) = 0
ndims(::Type{<:Ref}) = 0
iterate(r::Ref) = (r[], nothing)
iterate(r::Ref, s) = nothing
IteratorSize(::Type{<:Ref}) = HasShape{0}()
which means that it can be used in broadcasting as only objects that have axes
defined and support indexing can be used with broadcast
.
Fortunately it is easy to avoid writing Ref(A)
all the time.
Just define:
Base.broadcastable(e::example) = Ref(e)
and the machinery of broadcast
will work again as Base.broadcastable
is called on each argument of broadcast
.
More details about customizing broadcasting can be found here https://docs.julialang.org/en/v1/manual/interfaces/#man-interfaces-broadcasting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With