Search code examples
rebolred

How to modify each element of a block by "foreach" in red/rebol


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?


Solution

  • 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.