对于两个对象A
和B
,我们先前可以使用代码[A*A, A*B]
获得向量A .* [A, B]
。从Julia 0.7中的弃用警告来看,执行此操作的新方法似乎是使用第一个A的引用。因此它变为Ref(A) .* [A,B]
。
参考和广播操作之间似乎没有紧密的联系。此处的链接是什么?为什么首选使用“引用”(至少出于弃用警告)?
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]
答案 0 :(得分:8)
我在这里指的是Ref
的主要情况,即当您传递一个参数时(Ref
还有其他子类型,但在这里与我们无关)。
编写Ref(x)
会在对象x
周围创建一个可变的包装。包装器是一种非常简单的RefValue
类型,其定义如下:
mutable struct RefValue{T} <: Ref{T}
x::T
RefValue{T}() where {T} = new()
RefValue{T}(x) where {T} = new(x)
end
现在为什么有用,因为Ref
定义了以下实用程序功能:
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}()
这意味着它可以在广播中使用,因为只有定义了axes
且支持索引的对象才能与broadcast
一起使用。
幸运的是,很容易避免一直写Ref(A)
。
只需定义:
Base.broadcastable(e::example) = Ref(e)
broadcast
的机制将再次起作用,因为在Base.broadcastable
的每个参数上调用了broadcast
。
有关自定义广播的更多详细信息,请参见https://docs.julialang.org/en/latest/manual/interfaces/#man-interfaces-broadcasting-1。