Another option for a new syntax construct occurs to me, if (as this proposal seems to be uniquely focused on) you want to define local accumulators for any block. We could add to the family of special keywords do/end supports like else/catch/rescue/finally, say, acc.
This provides little value in the simplest if use-case, where you may as well use the else instead, but perhaps is nicer for complex cases and the for use-case.
else in with and catch in try/def already have precedence for accepting clauses and matching variables with ->. Perhaps we could accept clauses with the generator <- to indicate “generating” out into the external scope. So:
sum = 0
list =
for element <- [1, 2, 3] do
sum = element + sum
element * 2
acc
sum <- sum
end
list #=> [2, 4, 6]
sum #=> 6
This syntax says to me “after evaluating this block (however many times, each time for for) update the binding of the variable sum with the current value of sum, either before returning or iterating again.”
It allows for providing multiple reassignments with mulitple clauses, and doing other intermediate manipulations. Say,
i = 0
list = for element <- [1, 2, 3] do
element * i
acc
i <- i + 1
end
list #=> [0, 2, 6]
i #=> 3 (or 2?)
As others have pointed out before, while this functionality can be used to accumulate, especially if we’re adding it to other blocks than for, it really is just a rebinding tool. So perhaps rebind is a better keyword?
i = 0
list = for element <- [1, 2, 3] do
element * i
rebind
i <- i + 1
end
list #=> [0, 2, 6]
i #=> 3 (or 2?)