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

[REBOL] Re: foreach with block question

From: joel:neely:fedex at: 14-Oct-2001 8:27

Hi, Chris, chris palu wrote:
> > Try: > > > > foreach :row data [print bind row 'a] > > > > -jeff > > Hi. I've looked up bind in both the dictionary and user's guide, and > I'm still no wiser as to how and why bind works here. > > Anyone care to pound some understanding into my skull? >
I left my big hammer at work, but I'll try to offer some ideas! ;-) A REBOL word is just a name or symbol. Its value comes from the context that gives it meaning. Words in different contexts can have totally unrelated values, even when the words' names are spelled the same. Consider this example:
>> glorp: "I'm global!"
== "I'm global!"
>> wordblock: [glorp]
== [glorp]
>> some-fun: func [b [block!] /local glorp] [
[ glorp: "I'm local!" [ print [glorp] [ print b [ ]
>> some-fun wordblock
I'm local! I'm global! The word named "glorp" in the block is the externally-defined word. That fact doesn't change just because the block is handed in to the function. Therefore the second line of output is still referring to the value of the global "glorp" and not the local one. The role of BIND is to change the context of words in its first argument (if possible) to be the context of its second (sample) argument. Therefore, we can do this:
>> glorp: "I'm global!"
== "I'm global!"
>> glunk: "I'm global, too!"
== "I'm global, too!"
>> wordblock: [glorp glunk]
== [glorp glunk]
>> some-fun: func [b [block!] /local glorp foo] [
[ glorp: "I'm local!" [ foo: 42 [ print [glorp] [ print b [ bind b 'foo [ print b [ ] Similar exercise, but I added another global word to the block. In addition, I added an irrelevant local named FOO, just to show that the second argument to BIND is simply a *sample* word which indicates which context to use -- you don't need to worry about making names match.
>> print wordblock
I'm global! I'm global, too! Just what we expect.
>> some-fun wordblock
I'm local! I'm global! I'm global, too! I'm local! I'm global, too! Notice that after BIND does its thing, the first word in the block has been changed (bound) to the function's context. That's why the last output line is different from the second.
>> print wordblock
I'm local! I'm global, too! Notice too, that the change is permanent. Now the "glorp" in the first position of WORDBLOCK is the one in the function's context and not the global one. If this kind of aliasing is a problem, you could rewrite the demo function as:
>> some-fun: func [b [block!] /local glorp foo] [
[ glorp: "I'm local!" [ foo: 42 [ print [glorp] [ print b [ b: bind copy b 'foo [ print b [ ] (We also have to re-create WORDBLOCK...)
>> wordblock: [glorp glunk]
== [glorp glunk] Now we can do this:
>> some-fun wordblock
I'm local! I'm global! I'm global, too! I'm local! I'm global, too!
>> print wordblock
I'm global! I'm global, too! Since SOME-FUN modified a copy of the argument, the "glorp" in the original WORDBLOCK is not rebound. Hope this helps! -jn- -- ; sub REBOL {}; sub head ($) {@_[0]} REBOL [] # despam: func [e] [replace replace/all e ":" "." "#" "@"] ; sub despam {my ($e) = @_; $e =~ tr/:#/.@/; return "\n$e"} print head reverse despam "moc:xedef#yleen:leoj" ;