develooper Front page | perl.perl5.porters | Postings from July 2009

Re: [perl #67694] List::Util attaching to the wrong $_ when used inside given/when construct

Thread Previous | Thread Next
From:
Rafael Garcia-Suarez
Date:
July 21, 2009 03:45
Subject:
Re: [perl #67694] List::Util attaching to the wrong $_ when used inside given/when construct
Message ID:
b77c1dce0907210345h15fc7c54m2ab3567506148fa0@mail.gmail.com
2009/7/21 Bram <p5p@perl.wizbit.be>:
> Citeren Rafael Garcia-Suarez <rgarciasuarez@gmail.com>:
>
>> 2009/7/21 Bram <p5p@perl.wizbit.be>:
>>>
>>> This seem to happen because given creates a lexical $_. It also happens
>>> when
>>> for/foreach is used with a lexical $_:
>>
>> Hmm what ? No, given does not create a lexical $_ :
>
> I didn't look at the code only at the docs and the output :/
>
> from perldoc perlsyn:
> 'given(EXPR) will assign the value of EXPR to $_ within the lexical scope of
> the block, so it's similar to do { my $_ = EXPR; ... }'
>
> the output shows a different reference for $_ in the when block and in the
> s1 sub
>
>
>> from pp_entergiven :
>>
>>    if (PL_op->op_targ == 0) {
>>        SV ** const defsv_p = &GvSV(PL_defgv);
>>        *defsv_p = newSVsv(POPs);
>>        SAVECLEARSV(*defsv_p);
>>    }
>>    else
>>        sv_setsv(PAD_SV(PL_op->op_targ), POPs);
>>
>> What happens, at first glance, it that List::Util always uses the
>> global $_. (an "our $_" in the "first" block should solve the pb).
>
> Then what does in create in pp_entergiven?
> Doesn't it modify PL_defgv?
> (I have to admit being not familiar enough with the code to really
> read/understand it :( )

Ah, you're right. The parser has this line :
switch  :       label GIVEN '(' remember mydefsv mexpr ')' mblock
where mydefsv is an empty rule that lexicalizes $_.
But then the code I pasted above could probably be simplified.

> Adding an our $_ does solve the problem:
> With 's1 { our $_; print "\tblock:\t \$_ = " . \$_ . " (value: $_)"; };' the
> output becomes:
>
> Given/when block:
>        when-1:  $_ = SCALAR(0x942d7f0) (value: 1)
>        s1:      $_ = SCALAR(0x942d500) (value: a)
>        block:   $_ = SCALAR(0x942d500) (value: a)
>        when-2:  $_ = SCALAR(0x942d7f0) (value: 1)
>
>
> But why is this be nessesary?
> If given() does not create a lexical $_ then shouldn't the $_ in the block
> be the same as the global $_?
>
>>
>> We provide UNDERBAR and dUNDERBAR macros to access the current $_, be
>> it lexical or global.
>>
>> However we don't have (yet) an API to localize the current $_ as
>> needed in grep-like functions.
>>
>> I suppose that code from pp_grepstart could be copied in List::Util to
>> solve the bug.
>
> That would only work for the XS version right?
> (There is also a Pure Perl version...)

Yes.

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About