On "for (@foo)"

B

bill

Something like this burned me really bad once:

my @x = (1) x 3;
print "@x\n";
for my $y (@x) {
$y = 0;
}
print "@x\n";
__END__
1 1 1
0 0 0

It's as if the loop variable $y was a reference to the current
element of the array, except that it doesn't need to be dererenced.
Surprisingly, to me at least, this doesn't produce any errors:

for my $y (1..3) {
$y = 0;
}

Perl doesn't see the above as analogous to

1 = 0; # triggers "Can't modify constant item" error


OK, now, in an expression like this

for my $x (@X) {
# etc.
}

I assume that Perl keeps track of the index on @X correponding to
the current element. Is there a way to access this "current index"
from within a Perl program?

Thanks!

-bill
 
B

Ben Morrow

Quoth bill said:
Something like this burned me really bad once:

my @x = (1) x 3;
print "@x\n";
for my $y (@x) {
$y = 0;
}
print "@x\n";
__END__
1 1 1
0 0 0

It's as if the loop variable $y was a reference to the current
element of the array, except that it doesn't need to be dererenced.
Yes.

Surprisingly, to me at least, this doesn't produce any errors:

for my $y (1..3) {
$y = 0;
}

Perl doesn't see the above as analogous to

1 = 0; # triggers "Can't modify constant item" error

No: an array element is an lvalue, and modifiable.
OK, now, in an expression like this

for my $x (@X) {
# etc.
}

I assume that Perl keeps track of the index on @X correponding to
the current element. Is there a way to access this "current index"
from within a Perl program?

No, it simply keeps track of the current element. From that it can find
the next one.

Ben
 
B

Ben Morrow

Quoth "Andrew Palmer said:
OK, now, in an expression like this

for my $x (@X) {
# etc.
}

I assume that Perl keeps track of the index on @X correponding to
the current element. Is there a way to access this "current index"
from within a Perl program?

I think the only way to do what you want is like

for(my $i=0;$i<$#X;++$i)
{
$X[$i]=0;
}

You never need C-style loops:

for my $i (0..$#X) {
$X[$i] = 0;
}

Ben
 
A

Anno Siegel

Ben Morrow said:
Quoth "Andrew Palmer said:
OK, now, in an expression like this

for my $x (@X) {
# etc.
}

I assume that Perl keeps track of the index on @X correponding to
the current element. Is there a way to access this "current index"
from within a Perl program?

I think the only way to do what you want is like

for(my $i=0;$i<$#X;++$i)
{
$X[$i]=0;
}

You never need C-style loops:

for my $i (0..$#X) {
$X[$i] = 0;
}

$_ = 0 for @X;

Anno
 
B

bill

No: an array element is an lvalue, and modifiable.

Ah, yes. Somehow I thought that '..' returned a list. Come to
think of it, does anything in Perl *ever* return a list? I tried
other things that I *thought* returned lists, such as `command` or
m//g, in expressions like

for my $x (`seq 1 3`) {
$x = 0;
}

or

for my $x ('123' =~ m/\d/g) {
$x = 0;
}

but Perl did not complain, unlike the case

for my $x (1, 2, 3) {
$x = 0;
}

in which Perl kicks up a ruckus.

Then again, maybe this is not a terribly good test of listudinosity.

-bill
 
T

Tad McClellan

bill said:
Something like this burned me really bad once:


That can happen when you don't carefully read the documentation
for the features that you use.

It's as if the loop variable $y was a reference to the current
element of the array, except that it doesn't need to be dererenced.


The docs call it an "alias".

Perl's control structures are documented in:

perldoc perlsyn


The 3rd paragraph in the "Foreach Loops" section discusses the
behavior that you have observed.
 
J

J Krugman

That can happen when you don't carefully read the documentation
for the features that you use.

I don't think one could blame users from assuming that 2+2 is going
to evaluate to 4, no matter how clearly the documentations stated

Note that perl always evaluates 2+2 to 5.

The idea that the loop variable somehow channels through to the
array it is looping over is something I've never seen outside of
Perl.

jill
 
B

Ben Morrow

Quoth bill said:
Ah, yes. Somehow I thought that '..' returned a list. Come to
think of it, does anything in Perl *ever* return a list?

Hang on, no, I misread your code... my brane read it as

for my $y (@x) {

.. Hmmm; I'm puzzled too :). I think I'd call this a perl bug, especially
as

for my $y (1, 2, 3) {

fails...

Ben
 
B

Ben Morrow

Quoth (e-mail address removed)-berlin.de (Anno Siegel):
Ben Morrow said:
Quoth "Andrew Palmer said:
OK, now, in an expression like this

for my $x (@X) {
# etc.
}

I assume that Perl keeps track of the index on @X correponding to
the current element. Is there a way to access this "current index" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
from within a Perl program?
^^^^^^^^^^^^^^^^^^^^^^^^^^^
for my $i (0..$#X) {
$X[$i] = 0;
}

$_ = 0 for @X;

The OP was asking about more complex loops than the example given... :)

Ben
 
B

Ben Morrow

Quoth J Krugman said:
I don't think one could blame users from assuming that 2+2 is going
to evaluate to 4, no matter how clearly the documentations stated

Note that perl always evaluates 2+2 to 5.

The idea that the loop variable somehow channels through to the
array it is looping over is something I've never seen outside of
Perl.

It's incredibly useful, though, which is why it's there :)

Ben
 
D

David H. Adler

You never need C-style loops:

for my $i (0..$#X) {
$X[$i] = 0;
}

"Never"?

How about:

for ($i = 20; $i > 0; $i--) {
do_stuff_with($i);
}

(and, although I'm sure someone will come up with a way of avoiding the
c-style loop there, I'm not sure it'll be more readable)

On the other hand, I haven't finished my first coffee yet, so maybe I'm
missing something obvious.

dha
 
T

Tad McClellan

J Krugman said:
I don't think one could blame users from assuming that 2+2 is going
to evaluate to 4, no matter how clearly the documentations stated

Note that perl always evaluates 2+2 to 5.


If he had followed the advice I gave, he would not have been burned.
(which is why I followed up with it in the first place.)

If you are satisfied with "assuming" then you accept the possibility
of being burned.

If you don't want to accept that possibility, then look it up instead
of guessing from empirical observations.




Now, nobody reads all of the docs.

It is completely sensible to assume that foreach works like loops
in other languages and use it without reading its docs.

But when it appears to behave differently, the first thing to do
is look it up (ie. attempt to verify your assumption), not ask
hundreds of others to look it up for you.
 
P

Paul Lalli

You never need C-style loops:

for my $i (0..$#X) {
$X[$i] = 0;
}

"Never"?

How about:

for ($i = 20; $i > 0; $i--) {
do_stuff_with($i);
}

for my $i (reverse (1..20)){
do_stuff_with($i);
}
(and, although I'm sure someone will come up with a way of avoiding the
c-style loop there, I'm not sure it'll be more readable)


I disagree. <shrug>


Paul Lalli
 
B

Brian McCauley

Paul Lalli said:
for my $i (reverse (1..20)){
do_stuff_with($i);
}

This, of course, assumes that:

* 20 is a small number[1] because the optomisation of .. in for()
does not cope with reverse().

* do_stuff_with() does not alter its arguments. If it did I'd still
not use a C-style for, I'd use a while().

[1] er, 20 _is_ a small number but you know what I mean. :)

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
B

Brian McCauley

Ben Morrow said:
Quoth bill <[email protected]>:

No: an array element is an lvalue, and modifiable.

There is no array. 1..3 in the above is a list. Or rather it would
be a list if the .. operator was not handled as a special case in for().

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
J

J Krugman

In said:
But when it appears to behave differently, the first thing to do
is look it up (ie. attempt to verify your assumption), not ask
hundreds of others to look it up for you.

In fairness to the OP, as far as we know he never asked anyone to
"look it up for him", "it" being the case where he got burned.

jill
 
B

Brian McCauley

bill said:
Ah, yes. Somehow I thought that '..' returned a list.

If it were not for the special case then it would.

To remove the special case wrap it in do{}

for my $y ( do { 1..3 } ) {
$y = 0;
}

You still don't get an error, but now you don't get an error for a
different reason.

The fact is that the elements of a list that results from a
compulation are usually modifiyable. You can't say:

( something() )[0] = 666;

But the reson you can't say that is because there's a compile time
check "Can't modify list slice". If it wasn't for the compile time
check there'd be no run-time error.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
B

bill

There is no array. 1..3 in the above is a list. Or rather it would
be a list if the .. operator was not handled as a special case in for().

Now I'm mega-confused. From perlop:

Range Operators

Binary ".." is the range operator, which is really two
different operators depending on the context. In list
context, it returns an array of values counting (up by
^^^^^^^^
ones) from the left value to the right value.

I thought this is what Ben was alluding to. At any rate, as I
wrote in another post, other operators that perlop describe as
returning lists behave just like .. with regards to their return
value's modifiability via the loop variable (i.e. no error triggered).

-bill
 
B

Ben Morrow

Quoth bill said:
Now I'm mega-confused. From perlop:

Range Operators

Binary ".." is the range operator, which is really two
different operators depending on the context. In list
context, it returns an array of values counting (up by
^^^^^^^^
ones) from the left value to the right value.

I thought this is what Ben was alluding to.

As I said, I was wrong... this perldoc is also wrong. .. returns a list
in list context except (apparantly) in a for loop where it is optimized
away to simply incrementing the variable each time.
At any rate, as I
wrote in another post, other operators that perlop describe as
returning lists behave just like .. with regards to their return
value's modifiability via the loop variable (i.e. no error triggered).

I think Brian has explained this (his understanding is at any rate
better than mine): the result of a calculation performed on constant
terms is not itself constant. It's as though the result were explicitly
assigned to a temporary variable.

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top