Hi Joel

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! [
 a: 1
 init: func [n [integer!]] [a: n]
 set 'ob11 make object! [
  b: 10
  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
global context.

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

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]]
52 21

This feature is also very handy. I often wrap a whole script this way:

REBOL []
ctx-my-script [

.... all of the script code just as it was when its words were in the global
context

] 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
here.

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]
>> b
== [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
languages.

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?)

-Larry

----- Original Message -----
From: "Joel Neely" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Thursday, May 10, 2001 9:13 PM
Subject: [REBOL] Re: Embedded Object and Scope yet again...


> Hi, all!
>
> Just a small further demonstration that the term "embedded
> object" is of questionable significance in REBOL...
>
>     >> ob11: none
>     == none
>
> (just to make sure that there's nothing up my sleeve...)
>
>     >> ob1: make object! [
>     [    a: 1
>     [    init: func [n [integer!]] [a: n]
>     [    do [
>     [        ob11: make object! [
>     [            b: 10
>     [            init: func [n [integer!]] [b: n]
>     [            wot: func [] [a + b]
>     [            ]
>     [        ]
>     [    ]
>
> So where does that leave us?
>
>     >> source ob11
>     ob11:
>     make object! [
>         b: 10
>         init: func [n [integer!]][b: n]
>         wot: func [][a + b]
>     ]
>     >> source ob1
>     ob1:
>     make object! [
>         a: 1
>         init: func [n [integer!]][a: n]
>     ]
>
> But notice what A in OB11/WOT refers to!
>
>     >> ob11/wot
>     == 11
>     >> ob1/init 3
>     == 3
>     >> ob11/wot
>     == 13
>     >> ob11/init 20
>     == 20
>     >> ob11/wot
>     == 23
>
> So, is OB11 an "embedded object" in OB1 or not?
>
>   PRO:
>
>     It contains a word (A) belonging to the context of OB1.
>     It was created during the creation of OB1.
>
>   CON:
>
>     OB1 contains no reference to OB11.
>     OB11 is, in fact, a global name.
>
> Maybe the question contains too much baggage in the phrase
> "embedded object", eh wot?
>
> -jn-
> --
> To unsubscribe from this list, please send an email to
> [EMAIL PROTECTED] with "unsubscribe" in the
> subject, without the quotes.
>

-- 
To unsubscribe from this list, please send an email to
[EMAIL PROTECTED] with "unsubscribe" in the 
subject, without the quotes.

Reply via email to