参考文献和Julia中的广播之间有什么联系

时间:2018-08-23 20:28:51

标签: julia

对于两个对象AB,我们先前可以使用代码[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]

1 个答案:

答案 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