Reputation: 293
I want to modify each element of a block by foreach
. I tried like this but failed:
>> a: [3 4 5 6]
== [3 4 5 6]
>> foreach i a [i + 1]
== 7
>> a
== [3 4 5 6] ;; block a is not changed. What I want is [4 5 6 7]
Is there a better way to achieve it?
Upvotes: 0
Views: 199
Reputation: 6436
>> help forall
USAGE:
FORALL 'word body
DESCRIPTION:
Evaluates body for all values in a series.
FORALL is a native! value.
ARGUMENTS:
'word [word!] "Word referring to series to iterate over."
body [block!]
use forall
> a: [3 4 5 6]
== [3 4 5 6]
>> forall a [a/1: a/1 + 1]
== 7
>> probe a
[4 5 6 7]
== [4 5 6 7]
Upvotes: 1
Reputation: 333
As usual, no reply with your foreach.
a: [2 3 4 5]
b: copy []
foreach i a [append b i + 1]
and if you wish you can set a to b now
a: b
The problem with doing this in one step is that you do not have an index you can use here (despite the suggestive letter i, but that is representing the content of each item inside the block).
So now you can choose your favourite solution.
Upvotes: 1
Reputation: 2193
Changes that you made to values do not persist in a block itself. This ties back to your question about call-by-value parameter passing in Rebol and Red: you modify a copy on the stack (passed down to +
along with 1
), not the actual value slot that sits inside block a
.
To achieve what you want, you need to increment integers in-place, without pushing them on the stack. One way to do so is by using forall
.
>> block: [1 2 3]
== [1 2 3]
>> also block forall block [block/1: block/1 + 1]
== [2 3 4]
What forall
does is setting a word to a series and then incrementally bumping its index:
>> forall block [probe block]
[1 2 3]
[2 3]
[3]
Since it doesn't extract the actual values, you can access them using path notation, and then modify them in place. block/1
always pick the first value on each iteration.
Upvotes: 1