Как унаследовать от Реф в Юлии - PullRequest
4 голосов
/ 24 сентября 2019

Я изучал Джулию и хотел потратить некоторое время на его тестирование, добавив некоторые из моих любимых функциональных / неизменяемых конструкций в язык.В частности: типы для отложенных вычислений и обещаний, такие как типы задержки и обещания clojure.

И задержки, и обещания в принципе аналогичны Ref{T} с предупреждением о том, что (1) obj[] может потребоваться ждатьЗначение или выполнить вычисление перед возвратом, когда obj является обещанием или задержкой и (2) задержка / обещание может быть установлено только один раз и никогда не считываться до установки, поэтому является неизменным (по крайней мере, его интерфейс является интерфейсомнеизменный объект).

Моя интуиция здесь заключается в том, что и задержка, и обещание должны наследоваться от абстрактного неизменяемого типа ref, поскольку эта часть их поведения по крайней мере похожа;однако я не могу этого сделать:

abstract type ImmutableRef <: Ref end

недопустимый подтип в определении ImmutableRef

После просмотра исходного кода Julia, кажется,как и тип Ref, тип не объявляется типичным образом, а объявляется в основном коде Си Джулии.Можно ли унаследовать от Реф в Юлии?Если нет, то каким был бы идиоматический способ Джулии реализовать / организовать подобные типы ref-like?

1 Ответ

3 голосов
/ 24 сентября 2019

Как отметил Линдон, проблема заключалась в том, что вы не написали 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[]

Теперь, если мы пойдем на 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

Задержка должна быть очень похожа.

...