Seeking help, Ruby gurus ...
Consider the following Ruby object graph being constructed. It has forward
references in line (2) and (3) to x.forward_ref, something that will only
come into existence in line (7). It has a reference in line (4) and (5) to
an as-yet unresolved forward reference from line (2). And it operates on an
unresolved reference on line (6).
1) x = OpenStruct.new
2) y = OpenStruct.new(:f0 => x, :f1=>x.forward_ref)
3) z = [x, y, x.forward_ref]
4) w = y.f1
5) foo(y.f1)
6) bar(y.f1.f2)
7) x.forward_ref = Object.new
I want to build such structures lazily, but be lazy only when the laziness
is needed i.e. not for :f0=>x, or [x, y, ...], or y.f1. And I would like to
force resolution of (selected or all) unresolved references either:
a) at a time of my choosing (raising exceptions if needed), or
b) incrementally whenever a given reference becomes resolvable, or
c) when something is done with that reference i.e. some method invoked on it
(line 6).
I can assume that all accessors are just that: accessors i.e. no worry about
changing the order of mutator operations. The graph gets built monotonically
i.e. all slots are either uninitialized, or initialized, but not modified
once initialized.
I can assume that 'nil' is a distinguished sentinel value indicating an
uninitialized slot (instance variables, array at some index, hash value at
some key), but I don't know how much that will help for nil.method_missing
since even nil has a whole heap of defined methods. I can change any of the
assignment methods as needed.
What would be a good way to accomplish this? I was thinking I could create a
trail of proc-like things representing bits of suspended computation (a bit
like 'futures'), but can't really figure out how, or if it would be a good
approach. Do continuations offer some magic that would help?
Thanks!