user1134991
user1134991

Reputation: 3103

How to make Tcl loop variable exist just within the loop, akin to Perl foreach my

See Tcl shell code & results below:

% foreach a { 1 2 3 4 5 } { puts $a }
1
2
3
4
5
% puts $a
5

It would appear that variable a stays in the memory... In Perl, for example one can use:

foreach my $a

And have $a exist just during the looping. in Ruby, one can use closures:

[1,2,3,4,5].each{|a| puts a.to_s() }

In order to achieve the same.
Is there an elegant way to this in Tcl?
Thanks

Upvotes: 0

Views: 195

Answers (2)

Peter Lewerin
Peter Lewerin

Reputation: 13252

You can iterate within a closure:

apply {vals {foreach a $vals {puts $a}}} {1 2 3 4 5}

alternatively you can make the body a parameter (in which case the looping variable’s name should be a parameter too):

apply {{varName vals body} {foreach $varName $vals $body}} a {1 2 3 4 5} {puts $a}

If you call this myForeach or something, it looks less cumbersome:

set myForeach {{varName vals body} {foreach $varName $vals $body}}
apply $myForeach a {1 2 3 4 5} {puts $a}

You can also make this an interpreter macro:

set myForeach {{varName vals body} {foreach $varName $vals $body}}
interp alias {} myForeach {} apply $myForeach
myForeach a {1 2 3 4 5} {puts $a}

Documentation: apply, foreach, interp package, interp, puts, set

Upvotes: 1

Donal Fellows
Donal Fellows

Reputation: 137587

This is not the current semantics of foreach, and this is extremely unlikely to change in the near future as it would have a severe impact on many people's existing code. In particular, many people currently use:

foreach {a b c d} $someList break

Instead of doing:

lassign $someList a b c d

Because that was what worked in Tcl 8.4 and before and they've not updated their coding style since.

Upvotes: 0

Related Questions