[REBOL] Re: Obscure? You be the judge!
From: lmecir:mbox:vol:cz at: 15-May-2002 1:10
Hi Joel,
<<From: "Joel Neely">>
...
As Larry Wall said:
Just because something is obviously happening doesn't mean
that something obvious is happening.
;-)
However, I'm still left with a puzzled look on my face over
one aspect of this...
...
> when you 'make an 'object!, all strings, blocks and functions are
> copied.
> that allows for example in 'layout :
> box with[append init[my-inits]]
> without destroying the original in box.
> also blocks, like functions, are rebound.
> so [make child-proto []] gives a copy of 'dataref, not the original.
> but objects are not copied,
> so the 'face/feel are all the same after [make face[]].
> or in your case,
...
(Oh, by the way, did you find this documented anywhere, did you
just figure it out for yourself, or is there another path to
enlightenment? ;-)
<</Joel>>
<<L>>
I think, that he figured it out for himself...
<</L>>
<<Joel>>
...
Thanks to your explanation, I have a more compact example...
gub?: make object! [
data: [1]
proto: make object! [
number: 0
dataref: data
speak: func [] [print [number mold dataref]]
]
things: []
append things make proto [number: 1]
append things make proto [number: 2 dataref: data]
tweak-n-speak: func [blk [block!]] [
insert data blk
foreach thing things [thing/speak]
]
]
...which behaves as follows...
>> gub?/tweak-n-speak ["OK,"]
1 [1]
2 ["OK," 1]
My remaining puzzlement is over this contrast:
If I accept the description that (during the construction of
GUB?/PROTO) GUB?/DATA is copied and GUB?/PROTO/DATAREF is set
to refer to the copy, then that explains the behavior of
GUB?/THING/1 .
However, during the construction GUB?/THING/2 the additional
spec block *also* refers to GUB?/DATA , but apparently the copy
behavior does *not* occur (even though the referenced data value
is still only a block).
<</Joel>>
<<L>>
That "apparently" is incorrect. Here is a Rebol model of the MAKE PROTO
behaviour: (testing appreciated)
make-proto: function [
{MAKE PROTO simulation}
proto [object!]
spec [block!]
] [set-words object sw word value spc body] [
set-words: copy []
; get local words from proto
foreach word next first proto [
append set-words to set-word! word
]
; append all set-words from SPEC
parse spec [
any [
copy sw set-word! (append set-words sw) |
skip
]
]
; create a blank object with the desired local words
object: blank-object set-words
; set 'self in object to refer to the object
object/self: object
; copy the contents of the proto
repeat i (length? first proto) - 1 [
word: pick next first proto i
any-type? set/any 'value pick next second proto i
any [
all [string? get/any 'value set in object word copy value]
all [block? get/any 'value set in object word bind/copy
value in object word]
all [
function? get/any 'value
spc: load mold third :value
body: bind/copy second :value in object word
set in object word func spc body
]
any-type? set/any in object word get/any 'value
]
]
; bind the SPEC to the object
bind spec in object 'self
; evaluate it
spec-eval spec
; return the value of 'self as the result
return get/any in object 'self
]
<</L>>