Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[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: