首页 > 解决方案 > 如何从 Julia 中的 Ref 继承

问题描述

我一直在学习 Julia,想花一些时间通过向语言中添加一些我最喜欢的函数式/不可变结构来尝试一下。具体来说:延迟计算和承诺的类型,例如 clojure 的延迟和承诺类型。

延迟和承诺在原则上Ref{T}与以下警告相似:(1)obj[]可能需要等待一个值或运行计算才能返回何时obj是承诺或延迟,以及(2)延迟/承诺只能设置一次,并且永远不会在设置之前读取,因此是不可变的(至少,它的接口是不可变对象的接口)。

我的直觉是 delay 和 promise 都应该继承自抽象的不可变 ref 类型,因为它们的这部分行为至少是相似的;但是,我似乎不能这样做:

abstract type ImmutableRef <: Ref end

ImmutableRef 定义中的无效子类型

在浏览了 Julia 源代码之后,似乎该Ref类型没有以典型的方式声明,而是在 Julia 的核心 C 代码中声明。是否可以从 Julia 中的 Ref 继承?如果不是,那么实现/组织这些类 ref 类型的惯用 Julia 方式是什么?

标签: julia

解决方案


正如 Lyndon 所指出的,问题在于您没有写Ref{T}在类型签名中。

为了好玩,这是我实现的 promise 类型,尽管我确信有一种更优雅的方式可以更加努力地假装是不可变的。

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[]

现在,如果我们去 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

延迟应该非常相似。


推荐阅读