On "for (@foo)"

Discussion in 'Perl Misc' started by bill, May 28, 2004.

  1. bill

    bill Guest

    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
     
    bill, May 28, 2004
    #1
    1. Advertising

  2. bill

    Ben Morrow Guest

    Quoth 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.


    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

    --
    "The Earth is degenerating these days. Bribery and corruption abound.
    Children no longer mind their parents, every man wants to write a book,
    and it is evident that the end of the world is fast approaching."
    -Assyrian stone tablet, c.2800 BC
     
    Ben Morrow, May 28, 2004
    #2
    1. Advertising

  3. bill

    Ben Morrow Guest

    Quoth "Andrew Palmer" <atp5470 at fsu.edu>:
    > > 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

    --
    We do not stop playing because we grow old;
    we grow old because we stop playing.
     
    Ben Morrow, May 28, 2004
    #3
  4. bill

    Anno Siegel Guest

    Ben Morrow <> wrote in comp.lang.perl.misc:
    >
    > Quoth "Andrew Palmer" <atp5470 at fsu.edu>:
    > > > 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
     
    Anno Siegel, May 28, 2004
    #4
  5. bill

    John Bokma Guest

    John Bokma, May 28, 2004
    #5
  6. bill

    bill Guest

    In <c966vt$bkc$> Ben Morrow <> writes:


    >Quoth bill <>:
    >> 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.


    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
     
    bill, May 28, 2004
    #6
  7. bill <> wrote:
    >
    >
    >
    > 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.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, May 28, 2004
    #7
  8. bill

    J Krugman Guest

    In <> Tad McClellan <> writes:

    >bill <> wrote:
    >>
    >> 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.


    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
    --
    To s&e^n]d me m~a}i]l r%e*m?o\v[e bit from my a|d)d:r{e:s]s.
     
    J Krugman, May 28, 2004
    #8
  9. bill

    Ben Morrow Guest

    Quoth bill <>:
    > In <c966vt$bkc$> Ben Morrow <> writes:
    >
    >
    > >Quoth bill <>:
    > >> 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.

    >
    > 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

    --
    It will be seen that the Erwhonians are a meek and long-suffering people,
    easily led by the nose, and quick to offer up common sense at the shrine of
    logic, when a philosopher convinces them that their institutions are not based
    on the strictest morality. [Samuel Butler, paraphrased]
     
    Ben Morrow, May 28, 2004
    #9
  10. bill

    Ben Morrow Guest

    Quoth -berlin.de (Anno Siegel):
    > Ben Morrow <> wrote in comp.lang.perl.misc:
    > >
    > > Quoth "Andrew Palmer" <atp5470 at fsu.edu>:
    > > > > 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

    --
    'Deserve [death]? I daresay he did. Many live that deserve death. And some die
    that deserve life. Can you give it to them? Then do not be too eager to deal
    out death in judgement. For even the very wise cannot see all ends.'
     
    Ben Morrow, May 28, 2004
    #10
  11. bill

    Ben Morrow Guest

    Quoth J Krugman <>:
    > In <> Tad McClellan <> writes:
    >
    > >bill <> wrote:
    > >>
    > >> 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.

    >
    > 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

    --
    We do not stop playing because we grow old;
    we grow old because we stop playing.
     
    Ben Morrow, May 28, 2004
    #11
  12. On 2004-05-28, Ben Morrow <> wrote:

    > 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
    --
    David H. Adler - <> - http://www.panix.com/~dha/
    Your question doesn't make any sense. You might as well ask whether
    it is possible to grow vegetables from a painting, without becoming
    Wednesday first. - Abigail, c.l.p.misc
     
    David H. Adler, May 28, 2004
    #12
  13. J Krugman <> wrote:
    > In <> Tad McClellan <> writes:
    >
    >>bill <> wrote:
    >>>
    >>> 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.

    >
    > 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.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, May 28, 2004
    #13
  14. bill

    Paul Lalli Guest

    On Fri, 28 May 2004, David H. Adler wrote:

    > On 2004-05-28, Ben Morrow <> wrote:
    >
    > > 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
     
    Paul Lalli, May 28, 2004
    #14
  15. Paul Lalli <> writes:

    > On Fri, 28 May 2004, David H. Adler wrote:
    >
    > > On 2004-05-28, Ben Morrow <> wrote:
    > >
    > > > You never need C-style loops:

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

    >
    > 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\\
     
    Brian McCauley, May 28, 2004
    #15
  16. Ben Morrow <> writes:

    > Quoth bill <>:


    > > 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.


    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\\
     
    Brian McCauley, May 28, 2004
    #16
  17. bill

    J Krugman Guest

    In <> Tad McClellan <> writes:

    >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
    --
    To s&e^n]d me m~a}i]l r%e*m?o\v[e bit from my a|d)d:r{e:s]s.
     
    J Krugman, May 28, 2004
    #17
  18. bill <> writes:

    > In <c966vt$bkc$> Ben Morrow <> writes:
    >
    > >Quoth bill <>:
    > >> 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.

    >
    > 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\\
     
    Brian McCauley, May 28, 2004
    #18
  19. bill

    bill Guest

    In <> Brian McCauley <> writes:

    >Ben Morrow <> writes:


    >> Quoth bill <>:


    >> > 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.


    >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
     
    bill, May 28, 2004
    #19
  20. bill

    Ben Morrow Guest

    Quoth bill <>:
    > In <> Brian McCauley <> writes:
    >
    > >Ben Morrow <> writes:

    >
    > >> Quoth bill <>:

    >
    > >> > 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.

    >
    > >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.


    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

    --
    Outside of a dog, a book is a man's best friend.
    Inside of a dog, it's too dark to read.
    Groucho Marx
     
    Ben Morrow, May 28, 2004
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alex Vinokur
    Replies:
    7
    Views:
    439
    Jerry Coffin
    Sep 21, 2003
  2. Alex Vinokur
    Replies:
    4
    Views:
    477
    Ron Natalie
    Sep 24, 2003
  3. Replies:
    3
    Views:
    383
    John Roth
    Jul 29, 2005
  4. .rhavin grobert

    vector: Foo[5] == ((foo*)Foo) + 5 ?

    .rhavin grobert, Sep 23, 2008, in forum: C++
    Replies:
    4
    Views:
    394
    JaredGrubb
    Sep 24, 2008
  5. Replies:
    4
    Views:
    146
    Thomas 'PointedEars' Lahn
    Dec 23, 2007
Loading...

Share This Page