如何从Julia中的Ref继承

nbe*_*ben 5 julia

我一直在学习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方法是什么?

Mas*_*son 4

正如 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)

延迟应该非常相似。