我一直在学习Julia,并且想花一些时间通过在语言中添加一些我最喜欢的功能/不变结构来进行尝试。特别是:用于延迟计算和承诺的类型,例如clojure的延迟和承诺类型。
延迟和承诺在原则上都Ref{T}与警告类似,(1)obj[]在返回obj承诺或延迟时可能需要等待一个值或运行计算,然后(2)延迟/承诺只能设置一次,并且永远在设置之前读取,因此是不可变的(至少,其接口是不可变对象的接口)。
我的直觉是,延迟和承诺都应该继承自抽象的不可变ref类型,因为这部分行为至少是相似的。但是,我似乎无法做到这一点:
abstract type ImmutableRef <: Ref end
Run Code Online (Sandbox Code Playgroud)
ImmutableRef定义中的无效子类型
在仔细浏览了Julia的源代码之后,似乎该Ref类型不是以一种典型的方式声明的,而是在Julia的核心C代码中声明的。是否可以从Julia中的Ref继承?如果没有,那么实现/组织这类类似ref的类型的惯用Julia方法是什么?
正如 Lyndon 所指出的,问题在于您没有写入Ref{T}类型签名。
为了好玩,这是我的承诺类型的实现,尽管我确信有一种更优雅的方式可以付出更多的努力来假装不可变。
struct Promise{T} <: Ref{T}
r::Ref{T}
fufilled::Ref{Bool}
end
Promise{T}() where {T} = Promise{T}(Ref{T}(), Ref(false))
Promise() where {T} = Promise{Any}(Ref{T}(), Ref(false))
function Base.getindex(p::Promise)
@assert p.fufilled[] == true
p.r[]
end
function deliver(p::Promise{T}, val::U) where {U <: T}
p.r[] = val; p.fufilled[] = true
p
end
isrealized(p) = p.fufilled[]
Run Code Online (Sandbox Code Playgroud)
现在,如果我们进入 repl,我们可以检查其行为:
julia> x = Promise(); # If we know we'll deliver an Int then we should do Promise{Int}()
julia> isrealized(x)
false
julia> deliver(x, 1);
julia> x[]
1
Run Code Online (Sandbox Code Playgroud)
延迟应该非常相似。