结构体的属性在调用时赋值

结构体 Foo 有许多属性 val1, val2,...

mutable struct Foo
    val1
    val2
end

假设有些属性使用频率少,且计算耗时,希望初始化结构体 Foo 时,这部分属性暂不定义,而在被调用时才计算,比如

Foo() = ...
foo = Foo() # 初始化
1 + foo.val1 # 被调用,foo.val1 这时才真正被赋值
2 + foo.val1 # 第二次调用,直接取值

这个情况使用场景不少,想知道 Julia 下类似技巧怎么实现,或者用别的方式替代?
附 Python 的类似方法

class Foo():
    def __init__(self):
        self._val1  = None
    @property
    def val1(self):
        if self._val1 is None:
            self._val1 = 0
        return self._val1
    @val1.setter
    def val1(self, val):
        self._val1 = val

自己实现的话就是用 Nothing 当作占位符

mutable struct Foo{T1, T2}
    val1::T1
    val2::Union{T2,Nothing}
end
Foo(val1) = Foo(val1, nothing)

function get_val2(s::Foo)
    v = s.val2
    if isnothing(v)
        v = calculate_val2(...)
        s.val2 = v
    end
    return v
end

当然也可以考虑在 getproperty 函数的层级去做这件事情,比如说

function Base.getproperty(s::Foo, f::Symbol)
    v = getfield(s, f)
    if isnothing(v)
        v = calculate_field(s, f)
        setfield!(s, f, v)
    end
    return v
end
2 个赞

我怎么感觉有点像Lazy的需求?

1 个赞

LazilyInitializedFields.jl

3 个赞