Generating self-referencing immutable types in Julia

The Julia lang documentation explains how internal constructors and the new () function can be used to create self-referencing objects:

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

However, this approach does not work for immutable types, since it essentially uses the mutation of an incompletely initialized instance of x.

How can I create a self-referencing immutable object in Julia?

+4
source share
1 answer

Since you seem to have used Haskell before, I will adapt this answer in terms of functional programming. A common example of using self-referencing immutable types is creating a lazy list.

(.. ) , , .

, , , , 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 , , , , . , , , , , , .

+3

Source: https://habr.com/ru/post/1656722/


All Articles