[REBOL] Re: Scope? Any advice would be appreciated.
From: rebol:techscribe at: 28-Jan-2001 22:41
Hi David,
The body of a function is a block and behaves like a block. What strikes
you as an unusual behavior is part of REBOL's consistency. REBOL is
different from other programming languages in that it applies a
relatively small set of rules consistently across most of its types
(including functions). Just as you expect any block (even one that is
embedded in an outer block) to preserve its values, so too does REBOL
preserve the values of a block that is embedded in a block even though
the host block, besides being a block, also happens to be the body of a
function.
Given the block b that contains a single element, a block that in turn
contains three integers, all of which are 0
>> b: [ [0 0 0] ]
I can access the internal block using the path notation with the index
1:
>> b/1
== [0 0 0]
Now let me change the first 0 in the inner block to a 3
>> change b/1 3
== [0 0]
The block b now contains a block that contains the three integers 3, 0,
and 0
>> b/1
== [3 0 0]
Now for a simple function whose body contains a block that contains
three 0s
>> f: does [ [0 0 0] ]
I can access the body block of the function using the second function:
>> second :f
== [[0 0 0]]
I can assign the word c as a reference to the body block:
>> c: second :f
The wird c is now a reference to a block (namely the body block of the
function) like b is a reference to a block
>> c
== [[0 0 0]]
>> b
== [[3 0 0]]
I can now change the first value of c's embedded block:
>> change c/1 3
== [0 0]
Now c/1 looks like b/1:
>> c/1
== [3 0 0]
>> b/1
== [3 0 0]
Indeed the are equal:
>> b/1 = c/1
== true
Let me add a set-word! called block: to both blocks:
>> insert b [block:]
== [[3 0 0 ]]
and let's do the same to c
>> insert c [block:]
== [[3 0 0]]
What does b contain?
>> b
== [block: [3 0 0]]
What does c contain?
>> c
== [block: [3 0 0]]
If we try to get the value associated with block we get an error message
in both cases, because the blocks haven't been evaluated yet, and
therefore the set-words have not been associated with anything:
>> get b/1
** Script Error: block has no value.
** Where: get b/1
>> get c/1
** Script Error: block has no value.
** Where: get c/1
Now let's evaluate the function, which means that the block is reduced:
>> f
== [3 0 0 ]
Now we can get the value of the set-word! block: in c (recall that c is
simply a word associated with f's body block):
>> get c/1
== [3 0 0]
Now block: is associated with the block [0 0 0] in the function f. Let's
first get rid of this association, and then we'll look at b:
>> unset 'block
How about b? Since b's block is not associated with a function, we
cannot evaluate this non-existent function. We can, however, reduce the
block programmtically (reducing a block means evaluating its elements):
>> reduce b
== [[3 0 0]]
The reduction has caused the set-word block! to be associated with the
block [3 0 0] in the block b:
>> get b/1
== [3 0 0]
Finally, we can express evaluation of a function without arguments,
refinements, and locals as a block reduction:
eval-function: func [body [block!] [ reduce body ]
Let's first unset block:
>> unset 'block
If some f is a "does" function (i.e. without arguments, refinements, or
locals), then evaluating the function is the equivalent of passing the
function's body to our eval-function:
>> f: does [ block: [0 0 0] ]
>> first second :f
== block:
>> get first second :f
** Script Error: block has no value.
** Where: get first second :f
>> fbody: second :f
>> eval-function fbody
== [[0 0 0]]
>> get fbody/1
== [0 0 0]
>> first second :f
== block:
>> get first second :f
== [0 0 0]
Hope this makes it more digestable.
Elan
David Vydra wrote: