[REBOL] Re: Cloned object or ???
From: joel:neely:fedex at: 25-Jul-2001 9:08
Hi, Raimund,
Sorry for the delayed reply (I've been on vacation).
Raimund Dold wrote:
> I am playing with embedded objects and stumbled about a
> behaviour I just did not expect. I read through the docs
> but I could not find anything which clarified the issue
> for me. Maybe someone can help me.
>
You might find this old post from the mailing list of interest.
> [REBOL] Re: More on "embedded" objects (an enhancement)
>
> From: Joel Neely (view other messages by this author)
> Date: Wed, 16 May 2001 06:15:39
>
> Hello, self and list, ;-)
>
> As promised from last night... (The coding was trivial, but I
> wanted time to run a bunch of test cases and write a better
> description before posting.)
>
> Joel Neely wrote:
> >
> > A possible future enhancement (which it's too late for me
> > to tackle tonight) would be to add another refinement to
> > allow sharable attribute creation when instantiating a new
> > object from an existing object. I may take a quick look at
> > that in the morning.
> >
>
> The enhanced version with a /SHARED refinement appears below,
> followed by new and improved (I hope) documentation.
>
> 8<----------------------------------------------------------
>
> instantiate: func [
> [catch]
> spec1 [block! object!]
> /unique spec2 [block!]
> /shared spec3 [block!]
> /local ospec uspec uattr result
> ][
> ospec: copy []
> uspec: copy []
> uattr: to-word "; unique"
> if all [object? spec1 found? in spec1 uattr] [
> append uspec get in spec1 uattr
> ]
> if unique [
> append uspec spec2
> ]
> if 0 < length? ospec: copy/deep uspec [
> append ospec reduce [to-set-word uattr 0]
> ]
> if shared [
> append ospec spec3
> ]
> result: either object? spec1 [
> make spec1 ospec
> ][
> make object! append copy/deep spec1 ospec
> ]
> if 0 < length? uspec [
> set in result uattr uspec
> ]
> result
> ]
>
> 8<----------------------------------------------------------
>
> INSTANTIATE constructs objects.
>
> In the simplest case (i.e. no refinements -- ever!) it is
> almost the same as MAKE OBJECT! with the following exceptions:
>
> new-object: instantiate spec-block
>
> creates an object from the supplied block, but words in that
> block are NOT bound to the new objects context. In addition
>
> new-object: instantiate spec-object
>
> creates a new object from the supplied object, without the
> need for an empty block when no modifications are desired.
>
> The /UNIQUE refinement requires an additional block, which
> is combined with the original spec (block or object) to
> override and/or extend attributes for the new object, just
> as
>
> new-object: make spec-object extra-block
>
> can incorporate changes/additions to attributes. However,
> there's another difference. When creating an object via
>
> new-object: instantiate/unique spec-thing u-block
>
> (where SPEC-THING can be either a block or another object)
> the new object will distinguish between its "shared" parts
> and its "unique" parts. If yet another object is created
> later using
>
> newer-object: instantiate new-object
>
> the *current* state of the shared parts will be used as
> the basis of the newer object, but the *original* unique
> spec will be used to create a fresh copy of all unique parts.
> To illustrate:
>
> o1: instantiate/unique [
> a: 1
> ][
> b: 10
> gimme: func [] [print ["I contain" a "and" b]]
> ]
>
> creates an object with a shared A and unique B, with the
> following behavior
>
> >> o1/gimme
> I contain 1 and 10
> >> o1/a: 2
> == 2
> >> o1/b: 20
> == 20
> >> o1/gimme
> I contain 2 and 20
>
> Using O1 as the basis for a later object give the following
> results,
>
> >> o2: instantiate o1
> >> o2/gimme
> I contain 2 and 10
>
> where the unique attribute O2/B is initialized per the
> original unique spec block, rather than coming from the
> current state in O1.
>
> The /SHARED refinement allows an additional spec block to
> be supplied to override/extend the original specification,
> but *without* marking its content as unique. Therefore,
>
> >> o3: instantiate/shared o2 [a: 100]
> >> o3/gimme
> I contain 100 and 10
>
> overrides the current O2/A, but that change is not marked
> as unique. As the following transcript shows
>
> >> o3/a: 200
> == 200
> >> o3/b: 30
> == 30
> >> o3/gimme
> I contain 200 and 30
> >> o4: instantiate o3
> >> o4/gimme
> I contain 200 and 10
>
> the A attribute still comes from the current spec object,
> while future B attributes still revert to the original
> specification.
>
> The /SHARED refinement is allowed when building from a
> spec block as well. It will extend/override the base spec
> block, which creates "shared" attributes by default.
>
> Finally, both the /UNIQUE and /SHARED refinements are
> cumulative in effect:
>
> >> o: instantiate/unique [
> [ a: 1
> [ ][
> [ b: 10
> [ sum1: func [][a + b]
> [ ]
> >> o/a: 2
> == 2
> >> o/b: 20
> == 20
> >> o2: instantiate/shared o [
> [ c: 100
> [ sum2: func [][a + b + c]
> [ ]
> >> o3: instantiate/unique o2 [
> [ d: 1000
> [ sum3: func [][a + b + c + d]
> [ ]
>
> so that A and C are shared, while B and D are unique
>
> >> o3/a: 3
> == 3
> >> o3/b: 30
> == 30
> >> o3/c: 300
> == 300
> >> o3/d: 3000
> == 3000
> >> o4: instantiate o3
> >> o4/sum3
> == 1313
>
> Finally, of course (at last!), the most subtle and critical
> issue with /SHARED (or default) versus /UNIQUE is this:
> since the cumulative unique specifications in a prototype
> object are re-evaluated from a clean copy whenever that
> prototype object is INSTANTIATE-d,
>
> 1) any UNIQUE initialization activity will be re-evaluated
> in the combined context of the new object and the global
> context, and
>
> 2) any UNIQUE-ly "embedded" sub-objects will be re-created
> in the new context (1), while SHARED "embedded" sub-
> objects will simply refer back to the sub-object in the
> prototype object. Enclosing-object words in an embedded
> sub-object will refer to the original enclosure for
> SHARED (or default) sub-objects but will refer to the
> current enclosure for UNIQUE sub-objects.
>
> Hope this helps! (And if you read this far, I owe you a
> virtual cookie for your patience and endurance!)
>
> -jn-
--
This sentence contradicts itself -- no actually it doesn't.
-- Doug Hofstadter
joel<dot>neely<at>fedex<dot>com