gpt4 book ai didi

julia - 在 Julia 中生成自引用不可变类型

转载 作者:行者123 更新时间:2023-12-04 19:36:22 24 4
gpt4 key购买 nike

Julia lang 文档解释了如何使用内部构造函数和 new() 函数来构造自引用对象:

  type SelfReferential
obj::SelfReferential
SelfReferential() = (x = new(); x.obj = x)
end

然而,这种方法不适用于不可变类型,因为它本质上使用了未完全初始化的实例 x 的突变。

如何在 Julia 中生成自引用的不可变对象(immutable对象)?

最佳答案

由于您之前似乎使用过 Haskell,我将从函数式编程的角度来定制这个答案。自引用不可变类型的一个常见用例是创建惰性列表。

作为一种严格(即非惰性)语言,不可变对象(immutable对象)不可能直接引用自身。

但是,这并不排除使用可变对象(如 Ref)间接引用自身。或 Vector .

对于惰性结构的特殊情况,我可能建议将可变性限制在一个特殊的对象上,比如 Lazy{T} .例如,

import Base: getindex
type Lazy
thunk
value
Lazy(thunk) = new(thunk)
end

evaluate!(lazy::Lazy) = (lazy.value = lazy.thunk(); lazy.value)
getindex(lazy::Lazy) = isdefined(lazy, :value) ? lazy.value : evaluate!(lazy)

然后,例如,可以制作一个简单的惰性列表,如下所示:
import Base: first, tail, start, next, done, iteratorsize, HasLength, SizeUnknown
abstract List
immutable Cons <: List
head
tail::Lazy
end
immutable Nil <: List end

macro cons(x, y)
quote
Cons($(esc(x)), Lazy(() -> $(esc(y))))
end
end

first(xs::Cons) = xs.head
tail(xs::Cons) = xs.tail[]
start(xs::Cons) = xs
next(::Cons, xs) = first(xs), tail(xs)
done(::List, ::Cons) = false
done(::List, ::Nil) = true
iteratorsize(::Nil) = HasLength()
iteratorsize(::Cons) = SizeUnknown()

确实可以像在 Haskell 这样的语言中一样工作:
julia> xs = @cons(1, ys)
Cons(1,Lazy(false,#3,#undef))

julia> ys = @cons(2, xs)
Cons(2,Lazy(false,#5,#undef))

julia> [take(xs, 5)...]
5-element Array{Int64,1}:
1
2
1
2
1

这个功能可能看起来很复杂,但幸运的是它已经在 Lazy.jl 中实现了。 .

需要注意的是,由于类型不稳定性和可变类型,上述代码会产生大量开销。如果您使用 immutable 的目标不是表现力,而是表现力,那么显然这样的做法是不合适的。但通常不可能有一个引用自身的堆栈分配结构,因此在您想要最大性能的情况下,最好完全避免自引用。

关于julia - 在 Julia 中生成自引用不可变类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39858809/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com