"be consistent" PerlMonks

### For vs. While

by Andrew_Levenson (Hermit)
 on Dec 05, 2006 at 23:51 UTC Need Help??
Andrew_Levenson has asked for the wisdom of the Perl Monks concerning the following question:

I've been messing with my "Japh" thing (I tried to space it out for this node as best I could) and I noticed something peculiar (to me, at least):
```V(qw/74 401 211 79/);
sub V{while(@_){
\$v**=\$V?\$#_:\$V;
print(
map{
\$V<\$v?
chr(shift):
chr(reverse(pop))}\$_)
,\$V+=\$#_%2!=1?1:0}}

If I swap the while for a for, it only prints out "Ja".
Why might it do that?
I thought I may be cutting it off early by pop'ing off of the end, but that doesn't make any sense to me.

```

V(qw/74 401 211 79/);sub V{while(@_){\$v**=\$V?\$#_:\$V;
print(map{\$V<\$v?chr(shift):chr(reverse(pop))}\$_),\$V+=\$#_%2!=1?1:0}}

Replies are listed 'Best First'.
Re: For vs. While
by ikegami (Pope) on Dec 05, 2006 at 23:57 UTC

for (@array) loops until the number of iterations is greater than the number of elements in the array. When you reached the 3rd iteration of your for loop, @_ only has two elements (because of shift and pop), so the loop exits.

```sub f1 {
while (@_) {
print(shift);
}
print("\n");
}

sub f2 {
for (@_) {
print(shift);
}
print("\n");
}

sub f3 {
for (map \$_, @_) {
print(shift);
}
print("\n");
}

f1(map/./g, Japh);  # Japh
f2(map/./g, Japh);  # Ja
f3(map/./g, Japh);  # Japh

f2 iterates over the elements of @_.
f3 iterates over a premade list on the stack, so it doesn't matter that @_ changes.

Ahh, that makes perfect sense. Thanks!
```

V(qw/74 401 211 79/);sub V{while(@_){\$v**=\$V?\$#_:\$V;
print(map{\$V<\$v?chr(shift):chr(reverse(pop))}\$_),\$V+=\$#_%2!=1?1:0}}

That behaviour is specifically for for (@array). for (@array) is different than other forms of for (LIST). As soon as one iterates over anything but just an array, it's the size of the list on the stack that matters.

The real difference is that for (@array) is optimized to avoid flattening @array onto the stack. Instead, for (@array) navigates @array in place. For all other expressions, a list is formed on the stack and for iterates over that.

The following show the difference between iterating in place, and iterating over a list on the stack.

```sub f4 {
for (@_) {
print(\$_);
shift;
}
print("\n");
}

sub f5 {
for ((), @_) {
print(\$_);
shift;
}
print("\n");
}

f4(map/./g, Japh);  # Jp
f5(map/./g, Japh);  # Japh
Re: For vs. While
by Joost (Canon) on Dec 05, 2006 at 23:56 UTC
Pop and shift without arguments work on the @_ array (in subroutines at least), and modifying arrays update: that is; adding or removing elements - modifying elements is fine while looping through them with for(each) is IIRC not even officially supported. Even though it appears to do more or less what I'd expect.

In short it doesn't work for exactly the reason you mentioned. :-)

Create A New User
Node Status?
node history
Node Type: perlquestion [id://588005]
Approved by Joost
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2018-04-24 03:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My travels bear the most uncanny semblance to ...

Results (85 votes). Check out past polls.

Notices?