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

[REBOL] Trying to compose a block out of global and local bindings Re:

From: rebol:techscribe at: 7-Sep-2000 23:50

Hi princepawn, pretty much everything has already been said. (1) I just happened to notice that you redefine form (was pointed out) AND use reform:
>> source reform
reform: func [ "Forms a reduced block and returns a string." value "Value to reduce and form" ][ form reduce value ] You see that reform uses form. So at the time you evaluate reform, if we explicitly replace form by the value you assigned to it, then we get: reform: func [ "Forms a reduced block and returns a string." value "Value to reduce and form" ][ ["hi" name "welcome back"] reduce value ] reform no long performs a FORM on its argument! Since the result of a function is the value its body evaluates to (unless you use return at some point) in this case reform will simply return its reduced argument. Which leads me to ... ... (2) you use [ name: n print reform reduce b] ... reform reduce ... Recall the implementation of reform. The reform function performs a reduce on its argument, and therefore your explicit use of reduce is redundant. The whole difference between reform and form is that reform first REDUCEs its argument before it FORMs it. But you are using print ... ... and (3) print reduces its argument quite on its own anyway. The print function accepts a block as its argument and is not limited to an argument of type string!. Therefore you do not need to reduce or reform b. Passing b to print alone will work just fine, provided the name in the b block is bound to the context of foreach. Which leads me to ... ... A final word. What name evaluates to depends on the context in which it is defined. There are two instances of name involved in your function. One instance of name is bound to the global context: ["hi" name "welcome back"] where name is associated with the string "Bob". The other name is local to the function. When you set name to the value of n, then you are setting the instance of name that is bound to the local function to that value (obviously). The argument you pass to reduce, however, is the block that was constructed in the global context, and therefore the name instance it contains is the name bound to the global context. Actually you do not want the second name instance to be local to the letter2 function. You want the second name instance to be bound to the foreach (native!) function. So, you could say letter2: func [b] [ foreach name ["Sue" "Sally"] [ print bind b 'name ] ] Here BIND directs REBOL to associate all words contained in 'b with the closest context that contains the symbol name. Because 1. the context in which the BIND expression is being used is the block passed to foreach, and 2. a) because the first argument passed to foreach (foreach name ...) is an instance of the word name b) there therefore now exists an instance of the word name that is bound to foreach's context, 3. ==> therefore a) REBOL will identify foreach's context as the "closest" context in which 'name occurs. This is the context to which all words in the block b are now being bound, provided they are defined in foreach's context. b) Because of 3.a) the symbol name in the block b will be bound to the foreach context. (If the block b contained other words and some or all of these other words were also defined in the foreach context, then all these words would be bound to the foreach context as well. Words that are not defined in the foreach context remain bound to whichever context they originated in, when the block b was formed, or they remain unset!, if they were never set to a value to begin with). RESULT:
>> name: "Bob"
== "Bob"
>> message: ["hi" name "welcome back"]
== ["hi" name "welcome back"]
>> letter2: func [b] [
[ foreach name ["Sue" "Sally"] [ [ print bind b 'name [ ] [ ]
>> letter2 message
hi Sue welcome back hi Sally welcome back Note that as a side-effect the symbol name in the message block remains bound to the value it was last associated with in the letter2 function:
>> reduce message
== ["hi" "Sally" "welcome back"] If that should be relevant, i.e. you want to prevent the modification of the binding of the word name in the original message block, you can use bind/copy, which generates a duplicate of the block, before it binds it: letter2: func [b] [ foreach name ["Sue" "Sally"] [ print bind/copy b 'name ] ]
>> letter2 message
hi Sue welcome back hi Sally welcome back
>> reduce message
== ["hi" "Bob" "welcome back"] Note that the word used as foreach's first argument (foreach name ...) is not bound in the context of your letter2 function in which foreach is evaluated. It is bound in the context of foreach. Let us demonstrate that by collecting different instances of name into a block. We being with the global instance:
>> names: []
== []
>> name: "This is the global instance of name."
== "This is the global instance of name."
>> insert tail names 'name
== []
>> names
== [name]
>> reduce names
== ["This is the global instance of name."] Now a function that has a local instance of name f: func [/local name] [ name: "This is the function's local instance of name." insert tail names 'name print "In f. Before foreach." print mold names print names and includes a foreach loop that also uses an instance of the word (or symbol) name: foreach name ["This is the foreach instance of name."] [ insert tail names 'name print "In foreach." print mold names print names ] Now the complete f function including both instances of name: f: func [/local name] [ name: "This is the function's local instance of name." insert tail names 'name print "In f. Before foreach." print mold names print names foreach name ["This is the foreach instance of name."] [ insert tail names 'name print "In foreach." print mold names print names ] print "After foreach. In f." print mold names print names ] ... and let's run it:
>> f
In f. Before foreach. [name name] This is the global instance of name. This is the function's local instance of name. In foreach. [name name name] This is the global instance of name. This is the function's local instance of name. This is the foreach instance of name. After foreach. In f. [name name name] This is the global instance of name. This is the function's local instance of name. This is the foreach instance of name. Note that because we bound foreach's instance of name to the block's context, and the block is defined globally, the context foreach's name has been extended, i.e. it remains "alive". Hope this helps a little. Take Care, At 01:02 PM 9/7/00 -0700, you wrote:
>>> letter2: func [b /local name] [foreach n ["sally" "sue"][ name: n print
reform reduce b] ]
>>> form >== ["hi" name "welcome back"] > >>> name >== "bob" > >>> letter2 form >hi bob welcome back >hi bob welcome back > >... the only problem is I was hoping that the loop values in letter2 would
take precedence over the globally bound value of name and allow me to create a form letter of sorts.
>Could anyone help with this please? > >Get your FREE Email and Voicemail at Lycos Communications at >http://comm.lycos.com >
;- Elan [ : - ) ] author of REBOL: THE OFFICIAL GUIDE REBOL Press: The Official Source for REBOL Books http://www.REBOLpress.com visit me at http://www.TechScribe.com