[REBOL] Re: En Masse block operations
From: joel:neely:fedex at: 16-Oct-2001 14:09
Hi, Tim,
Tim Johnson wrote:
> I see Ryan's opinion not to use 'foreach.....
> Could you comment on his opinion on this.
>
> (I've seen references to a foreach "bug" and
> I almost never use it myself.)
>
AFAIK there's no bug involved, but it is possible to misunderstand
what FOREACH (and REPEAT, for that matter) are doing. Here's your
original sample block:
>> blk
== [[1 2 3 4] [5 6 7 8] [9 10 11 12] [13 14 15 16 17] "one"]
Let's go through it with FOREACH...
>> foreach item blk [print item: next item]
2 3 4
6 7 8
10 11 12
14 15 16 17
ne
... and then look at the block again ...
>> blk
== [[1 2 3 4] [5 6 7 8] [9 10 11 12] [13 14 15 16 17] "one"]
The block itself is unchanged. The (local) word ITEM was set to
each value in the block in turn. This means that the expression
item: next item
in the above code is changing the position to which ITEM refers,
but not changing the (explicit, literal) series reference that is
in each position of BLK. The same thing happens if you use REPEAT
as follows:
>> repeat item blk [print item: next item]
2 3 4
6 7 8
10 11 12
14 15 16 17
ne
>> blk
== [[1 2 3 4] [5 6 7 8] [9 10 11 12] [13 14 15 16 17] "one"]
The point is that if you want to mutate the values in BLK, you're
going to have to do one of two things:
1) work directly with the references in BLK (or an alternate
reference to BLK), or
2) compute a new block based on the old values in BLK and set BLK
to refer to that new block.
The first alternative could be written as
>> forall blk [ blk/1: next blk/1 ] blk: head blk
== [[2 3 4] [6 7 8] [10 11 12] [14 15 16 17] "ne"]
>> blk
== [[2 3 4] [6 7 8] [10 11 12] [14 15 16 17] "ne"]
and could be undone by
>> forall blk [blk/1: head blk/1] blk: head blk
== [[1 2 3 4] [5 6 7 8] [9 10 11 12] [13 14 15 16 17] "one"]
The second alternative could be coded in-line or done via MAP,
as discussed in my prior email.
>> loop 5 [print mold blk: map blk func [s] [next s]]
[[2 3 4] [6 7 8] [10 11 12] [14 15 16 17] "ne"]
[[3 4] [7 8] [11 12] [15 16 17] "e"]
[[4] [8] [12] [16 17] ""]
[[] [] [] [17] ""]
[[] [] [] [] ""]
>> blk: map blk func [s] [head s]
== [[1 2 3 4] [5 6 7 8] [9 10 11 12] [13 14 15 16 17] "one"]
In any event, I'm not aware of a FOREACH "bug" and use it all
the time.
HTH!
-jn-
--
This sentence contradicts itself -- no actually it doesn't.
-- Doug Hofstadter
joel<dot>neely<at>fedex<dot>com