Shorthand for($scalar) loops and resetting pos($scalar)

Discussion in 'Perl Misc' started by Clint Olsen, Nov 12, 2003.

  1. Clint Olsen

    Clint Olsen Guest

    Hi:

    I'm currently using 5.8.1, and I'm writing a lexer which operates on a
    scalar that has the contents of the entire file. I'm using the usual
    suspects (/gc and \G) in all of my patterns to remember where I was.

    However, I've noticed a technique in Parse::Yapp which does the following:

    LOOP: for ($scalar) {

    /whitespace/ and next LOOP;
    /pattern/ and this;
    /patern1/ and that;
    }

    What exactly is the for() loop doing that's different than $_ = $scalar?

    The documentation is pretty scant on this subject - conditions under which
    pos() will be reset. Generally a for loop consists of an initialization, a
    test, and an optional chunk to do at the end of the code BLOCK.

    Thanks,

    -Clint
    Clint Olsen, Nov 12, 2003
    #1
    1. Advertising

  2. Clint Olsen

    Ben Morrow Guest

    Clint Olsen <> wrote:
    > LOOP: for ($scalar) {
    >
    > /whitespace/ and next LOOP;
    > /pattern/ and this;
    > /patern1/ and that;
    > }
    >
    > What exactly is the for() loop doing that's different than $_ = $scalar?


    1. Giving you a loop to 'next' to,
    2. localising $_,
    3. aliasing $_ rather than simply assigning it: ie. modifying $_ in
    the loop will modify $scalar outside it.

    The loop could be rewritten

    LOOP: {
    local *_ = \$scalar;
    ...
    }

    but that's a little *too* incomprehensible, even for me :).

    This is quite a common idiom in Perl: it's sort-of like the 'with'
    keyword in VB et al.

    > The documentation is pretty scant on this subject - conditions under which
    > pos() will be reset.


    From perlop:

    | A failed match normally resets the search position to the beginning
    | of the string, but you can avoid that by adding the "/c" modifier
    | (e.g. "m//gc"). Modifying the target string also resets the search
    | position.

    > Generally a for loop consists of an initialization, a test, and an
    > optional chunk to do at the end of the code BLOCK.


    That is a C-style for() loop, which is not much used in Perl and is
    actually a while() loop in disguise :). The for() loop above is the
    *other* type of for() loop, which some people call a 'foreach' loop to
    disambiguate.

    Ben

    --
    I've seen things you people wouldn't believe: attack ships on fire off the
    shoulder of Orion; I've watched C-beams glitter in the darkness near the
    Tannhauser Gate. All these moments will be lost, in time, like tears in rain.
    Time to die. |-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-|
    Ben Morrow, Nov 12, 2003
    #2
    1. Advertising

  3. Clint Olsen

    Clint Olsen Guest

    On 2003-11-12, Ben Morrow <> wrote:
    >
    > 1. Giving you a loop to 'next' to,


    Ok, makes sense. Although you don't really need the for keyword to do
    that, as you have shown in later code.

    > 2. localising $_,


    I've never used local variables. The documentation says you should
    generally avoid them in favor of lexically scoped variables.

    > 3. aliasing $_ rather than simply assigning it: ie. modifying $_ in
    > the loop will modify $scalar outside it.


    How is that different than references? Sorry if my globbing/aliasing
    knowledge is a bit sparse. I didn't start using Perl until version 5.X.

    > The loop could be rewritten
    >
    > LOOP: {
    > local *_ = \$scalar;
    > ...


    You don't mean $_?

    >| A failed match normally resets the search position to the beginning
    >| of the string, but you can avoid that by adding the "/c" modifier
    >| (e.g. "m//gc"). Modifying the target string also resets the search
    >| position.


    Right, but it totally leaves out the case of when assigning a reference to
    that scalar loses info or this "local" construct which appears to preserve
    pos(). Obviously when you have a copy of a scalar, that scalar's pos()
    should be 0 (or undef), but the conditions under which a copy is made is
    obviously clouded in ths funky for() loop.

    > That is a C-style for() loop, which is not much used in Perl and is
    > actually a while() loop in disguise :). The for() loop above is the
    > *other* type of for() loop, which some people call a 'foreach' loop to
    > disambiguate.


    Yeah, it's as clear as mud :) I read page on perlsyn, and the for loop
    does mention some similarity between for and foreach and while, but it
    doesn't go any further than that.

    -Clint
    Clint Olsen, Nov 12, 2003
    #3
  4. Clint Olsen <> wrote:

    > However, I've noticed a technique in Parse::Yapp which does the following:
    >
    > LOOP: for ($scalar) {
    >
    > /whitespace/ and next LOOP;
    > /pattern/ and this;
    > /patern1/ and that;
    > }
    >
    > What exactly is the for() loop doing that's different than $_ = $scalar?



    Nothing.

    It just saves you from typing a lot of "$scalar =~" thingies.

    ie:

    $scalar =~ /whitespace/ and next LOOP;
    $scalar =~ /pattern/ and this;
    $scalar =~ /patern1/ and that;


    > Generally a for loop consists of an initialization, a
    > test, and an optional chunk to do at the end of the code BLOCK.



    The "for" and "foreach" keywords are interchangeable in Perl,
    so the above is the same as:

    LOOP: foreach ($scalar) {

    only with less typing.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Nov 12, 2003
    #4
  5. [posted & mailed (maybe?)]

    On Wed, 12 Nov 2003, Clint Olsen wrote:

    >On 2003-11-12, Ben Morrow <> wrote:
    >>
    >> 2. localising $_,

    >
    >I've never used local variables. The documentation says you should
    >generally avoid them in favor of lexically scoped variables.


    Yes, but there are some variables that CANNOT be lexically scoped; these
    are generally punctuation variables, like $_ and @_ and $/.

    >> 3. aliasing $_ rather than simply assigning it: ie. modifying $_ in
    >> the loop will modify $scalar outside it.

    >
    >How is that different than references? Sorry if my globbing/aliasing
    >knowledge is a bit sparse. I didn't start using Perl until version 5.X.


    An alias is another name for a variable, whereas a reference is another
    name for the LOCATION of a variable.

    $foo = 'blah';
    @foo = qw( fee fie foe fum );
    *bar = \@foo;
    $bar = 'boo';

    print "$foo $bar[2]"; # blah foe

    The second line makes @bar an alias for @foo; that is, any changes to @foo
    change @bar, and vice-versa. If we had written

    *bar = \*foo;

    instead, then the print() line would have read 'boo foe', because ALL
    'bar' variables would be aliases for ALL 'foo' variables. What's
    important to realize here is that, because of the use of glob notation,
    'bar' here is a global variable; it cannot be lexical, because lexical
    variables are not related to each other -- they have no concept of a glob.

    >> LOOP: {
    >> local *_ = \$scalar;
    >> ...

    >
    >You don't mean $_?


    No, that would make $_ a REFERENCE to $scalar. This way makes it an alias
    to $scalar. See above.

    >>| A failed match normally resets the search position to the beginning
    >>| of the string, but you can avoid that by adding the "/c" modifier
    >>| (e.g. "m//gc"). Modifying the target string also resets the search
    >>| position.

    >
    >Right, but it totally leaves out the case of when assigning a reference to
    >that scalar loses info or this "local" construct which appears to preserve
    >pos(). Obviously when you have a copy of a scalar, that scalar's pos()
    >should be 0 (or undef), but the conditions under which a copy is made is
    >obviously clouded in ths funky for() loop.


    It's not funky, it's a Perl-style loop, also known as 'foreach'. I don't
    know what you mean, though:

    $x = "jeff";
    pos($x) = 2;
    for ($x) {
    print pos($x), " " , pos($_), "\n"; # 2 2
    }

    --
    Jeff Pinyan RPI Acacia Brother #734 2003 Rush Chairman
    "And I vos head of Gestapo for ten | Michael Palin (as Heinrich Bimmler)
    years. Ah! Five years! Nein! No! | in: The North Minehead Bye-Election
    Oh. Was NOT head of Gestapo AT ALL!" | (Monty Python's Flying Circus)
    Jeff 'japhy' Pinyan, Nov 12, 2003
    #5
  6. Clint Olsen

    Clint Olsen Guest

    I did get your email as well. Was there a problem initially sending it?

    On 2003-11-12, Jeff 'japhy' Pinyan <> wrote:
    >
    > Yes, but there are some variables that CANNOT be lexically scoped; these
    > are generally punctuation variables, like $_ and @_ and $/.


    Right. I never tried to make them lexically scoped.

    > $foo = 'blah';
    > @foo = qw( fee fie foe fum );
    > *bar = \@foo;
    > $bar = 'boo';
    >
    > print "$foo $bar[2]"; # blah foe
    >
    > If we had written
    >
    > *bar = \*foo;
    >
    > instead, then the print() line would have read 'boo foe', because ALL
    > 'bar' variables would be aliases for ALL 'foo' variables.


    [some snipping]

    Ahh, this is an excellent explanation, thanks.

    > No, that would make $_ a REFERENCE to $scalar. This way makes it an alias
    > to $scalar. See above.


    Ok, makes much more sense now.

    > It's not funky, it's a Perl-style loop, also known as 'foreach'. I don't
    > know what you mean, though:
    >
    > $x = "jeff";
    > pos($x) = 2;
    > for ($x) {
    > print pos($x), " " , pos($_), "\n"; # 2 2
    > }


    What I meant was it wasn't entirely obvious how $_ is being set in the
    for() loop, and this is the key to preserving pos() for $x in and out of
    the loop. Any attempt to assign $_ without using globbing wouldn't have
    worked, right?

    Thanks,

    -Clint
    Clint Olsen, Nov 13, 2003
    #6
  7. [posted & mailed]

    On Thu, 13 Nov 2003, Clint Olsen wrote:

    >I did get your email as well. Was there a problem initially sending it?


    I couldn't be sure if the email address was valid (and was too lazy to
    check out olsen.net).

    >What I meant was it wasn't entirely obvious how $_ is being set in the
    >for() loop, and this is the key to preserving pos() for $x in and out of
    >the loop. Any attempt to assign $_ without using globbing wouldn't have
    >worked, right?


    Right; just copying the contents of $x to $y doesn't transfer $x's pos()
    to $y.

    --
    Jeff Pinyan RPI Acacia Brother #734 2003 Rush Chairman
    "And I vos head of Gestapo for ten | Michael Palin (as Heinrich Bimmler)
    years. Ah! Five years! Nein! No! | in: The North Minehead Bye-Election
    Oh. Was NOT head of Gestapo AT ALL!" | (Monty Python's Flying Circus)
    Jeff 'japhy' Pinyan, Nov 13, 2003
    #7
    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. Replies:
    7
    Views:
    407
  2. Mark

    Replace scalar in another scalar

    Mark, Jan 27, 2005, in forum: Perl Misc
    Replies:
    4
    Views:
    163
    Arndt Jonasson
    Jan 27, 2005
  3. Me
    Replies:
    2
    Views:
    243
  4. Archos

    Shorthand operator for AND, NOT

    Archos, Dec 19, 2011, in forum: Javascript
    Replies:
    5
    Views:
    579
    Archos
    Dec 22, 2011
  5. prati
    Replies:
    0
    Views:
    444
    prati
    Oct 27, 2012
Loading...

Share This Page