Why Are Loop Variables Taken Literally?

It's important.

The problem is that since the system takes all bindings seriously, there are many places where if you have something bound and it's not expected, you'll get an error.

For instance: any SET-WORD in a MAKE OBJECT! spec that has a binding creates a contradictory situation. You don't know if the person was intending an assignment to the specific word they composed in, or if a field was supposed to be created for it.

Having a lightweight way to say "don't bind this" really makes a difference in expressivity.

Red changed this to be the default semantic. They didn't want to pay to deep walk and bind the loop body. Ren-C doesn't deep walk the body and mutably bind it (for all the reasons that's a bad idea) so it's not avoiding as much work. You do save on making a new variable, if you already had one on hand. :man_shrugging:

So it's not really that big a deal for performance. It's more stylistic, e.g. if you have code outside the loop body that expects to be able to operate on the item:

x: ()

helper: does [x + 1]

for-each $x [1 2 3] [helper]

Otherwise you'd have to pass the value explicitly:

helper: lambda [arg] [arg + 1]

for-each x [1 2 3] [helper x]

So in that sense you can get some more efficiency and briefer code. It's a feature worth knowing about. But I think creating a new variable is the right default--and Red's choice is a mistake.

1 Like