[REBOL] Re: Embedded Object and Scope yet again...
From: larry:ecotope at: 10-May-2001 23:10
You have been coming up with some fun examples lately. Maybe I can throw a
little light on the topic.
First the effect in your example is also obtained with this code:
ob1: make object! [
init: func [n [integer!]] [a: n]
set 'ob11 make object! [
init: func [n [integer!]] [b: n]
wot: func  [a + b]
All of your tests below give the same result as when using the do 
construct. The form above is the poor man's module capability (until the
real thing comes along in REBOL/Core 3). Carl, myself, and many others often
use this construction. In fact, much of VID is written using this mechanism.
For example, if you do source LAYOUT, you will find that layout calls a
number of functions like TRACK, EXPAND-SPECS, DO-FACETS, GROW-FACETS, etc.
which are not defined globally. This works because LAYOUT was defined in the
VID object, but it was defined using SET as above and thus exported to the
This is very useful because it allows you to export a few interface
functions for the object to the global context, while at the same time being
able to reference all of the words in the "parent" object. At the same time,
the global context is shielded from the many named data-structures, layouts,
sub-objects, styles, helper functions, etc. which are included in the parent
So how does all this work? There are others who can surely give a better
explanation than I can, but I will make a few comments. There are stages in
object creation, and in one of the early stages the object spec block is
scanned for all first-level set-words. A context for the object is created
with these words bound to it.
After this stage, the code in the object spec is executed, in exactly the
same way as a block of code in the global context. The only difference is
that those words which occurred in the spec-block as set-words are bound to
the objects context. Any code can appear and will be executed. For example:
>> x: 21 ob: make object! [ a: 52 print [a x]]
This feature is also very handy. I often wrap a whole script this way:
.... all of the script code just as it was when its words were in the global
] end ctx-my-script
The global context is protected from all of the set-words used in the
script. There are some extra precautions when using vid which I will skip
There are a couple of facts about "embedded" objects which are good to know:
1) Sub-objects which are defined with a set-word in the parent object are
treated differently than other datatypes when the object is cloned.
Sub-objects are not cloned, the pointer (which what a word really
references) still points to the original sub-object. Other datatypes are
copied into the cloned object.
2) Sub-objects exported with your do  construct or by using SET are not
really "embedded", the words which reference them are global, but the words
contained in their definition blocks are bound to the context of the object
in which they are created. To me it is similar to this example:
>> b:  repeat j 3 [use [x][x: j append b 'x]]
== [x x x]
== [x x x]
>> reduce b
== [1 2 3]
The word b is in the global context, it's value is a block which contains
the words x, x, and x each of them created in a different unnamed context.
You can do much the same thing in LISP, Scheme or other symbolic programming
Your conclusion can be extended to state that it is often misleading to
apply the concepts of object-oriented programming in trying to understand
REBOL. REBOL's objects do not support the key concepts of OO. They are
primarily name-spaces, and have their own distinctive properties relating to
the underlying symbolic language. They are one-of-kind objects, sometimes
called objects by prototype in the books.
Perhaps others will contribute further insights or corrections. (Carl, Jeff,
Holger, Gabriele, Ladislav?)