Question

map-each can be used to evaluate some code for every member in a collection, and aggregate the results of the evaluation in a block:

>> values: map-each x [1 2] [
    print ["Doing mapping for" x]
    x * 10
   ]
Doing mapping for 1
Doing mapping for 2
== [10 20]

I was building a block of blocks in this way. But I forgot that since blocks aren't evaluated by default, the x would be left as-is and not get the value I wanted:

>> blocks: map-each x [1 2] [
    print ["Doing mapping for" x]
    [x * 10]
   ]
Doing mapping for 1
Doing mapping for 2
== [[x * 10] [x * 10]]

No surprise there. After the evaluation x has no value--much less the ability to take on many values:

>> probe x
** Script error: x has no value

So it's too late, the evaluation must be done with a REDUCE or COMPOSE inside the body of the map-each. But...

>> reduce first blocks
== [20]

>> reduce second blocks
== [20]

The evaluations of items in the result block don't throw an error, but behave as if x had the value of the last iteration.

How is it doing this? Should it be doing this?

Was it helpful?

Solution

Just like 'FOREACH, 'MAP-EACH binds the block you give it within a context it creates and executes it there.

the X is never created globally. the fact that you gave it a word (and not a lit-word) as an argument is managed by the function's interface which probably uses the lit-word notation, and uses the word given, as-is, un-evaluated, instead of the value it may contain.

for this reason, the X used in your call to map-each doesn't trigger a

** Script error: x has no value

since map-each is grabbing it before it gets evaluated and only uses the word as a token, directly.

To illustrate how binding works more vividly and to show how 'X may survive existence past its original context, here is an example which illustrates the foundation of how words are bound in Rebol (and the fact that this binding persists).

look at this example:

a: context [x: "this"]  
b: context [x: "is"]  
c: context [x: "sensational!"]

>> blk: reduce [in a 'x   in b 'x   in c 'x]
== [x x x]

x: "doh!"
== "doh!"

>> probe reduce blk
["this" "is" "sensational!"]

We created a single block with three 'X words, but none of them are bound to the same context.

Because the binding in Rebol is static, and scope doesn't exist, the same word can have different values, even when they are being manipulated in the same context (in this case the console is the global | user context).

This is the penultimate example of why a word is really NOT a variable in Rebol.

OTHER TIPS

blocks: map-each x [1 2] [
    print ["Doing mapping for" x]
    [x * 10]
]

probe bound? first blocks/1

gives this

Doing mapping for 1
Doing mapping for 2
make object! [
    x: 2
]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top