Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Here is a small code which I is not working as I expect:

use feature 'switch'; my $h = {s => 'ababa'}; $h->{s} =~ m/^/g; while (1) { given ($h->{s}) { when(/a/g) { print pos $h->{s}, "\n" } default { exit } } }

On my version of Perl (v5.14.2), I get:

0 0 0

But I expected:

1 3 5

The /g modifier to the regex obviously works because the loop stops after three iterations. So why does pos() fails to report the correct value ?

If I replace the given/when by an if statement then everything works fine.

Any helps understanding this will be appreciated (even more if I can get the value of pos()). Thanks!

Replies are listed 'Best First'.
Re: Using pos() inside given/when
by Kenosis (Priest) on May 10, 2013 at 00:34 UTC
Re: Using pos() inside given/when
by Athanasius (Archbishop) on May 10, 2013 at 02:48 UTC

    Kenosis and educated_foo have answered the question. I just want to add a few comments:

    1. On my version of perl (v5.16.0) the code in the OP produces an infinite loop.

    2. The real code is, no doubt, more complex than the code in the example. But I suspect that, even so, the logic could be significantly clarified by rearranging the loops. Certainly, the example as given can be written with just one loop:

      print pos $h->{s}, "\n" while $h->{s} =~ /a/g;
    3. The line:

      $h->{s} =~ m/^/g;

      is presumably there only to reset pos, in which case I suggest the following would be clearer:

      pos($h->{s}) = undef;

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Thanks for your answers. Switching to a for solved that problem (I could not have rewritten it with a simple loop, as I have a lot of when in a Lex-like code).

      If I understand correctly the fact that in v5.16 the same code gives an infinite loop, it's that the given's version of $_ have been "fixed", in the sense that a new scalar is now created for each iteration (hence the pos() function and the matching are in accord). But the same thing with the for loop will still work as I expect ?

      If the when construct does not care from where does the $_ variable comes from, do you know what was the need to introduce given rather than just stick with for ?

      Anyway, thanks for your help!

        for and given both use $_. The difference is that for uses our $_ and aliases it to the item, while given copies (though I believe it's a cheap optimized copy) the item to my $_.

        package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Using pos() inside given/when
by educated_foo (Vicar) on May 10, 2013 at 01:09 UTC
    You've fallen into the "broken things added to Perl since 5.008" trap. Specifically, given/when uses lexical $_, which is a misfeature. You're best off avoiding "features" added to Perl since about 5.006.
    Just another Perler interested in Algol Programming.