Skip Menu |
 

This queue is for tickets about the Scalar-List-Utils CPAN distribution.

Report information
The Basics
Id: 95409
Status: open
Priority: 0/
Queue: Scalar-List-Utils

People
Owner: Nobody in particular
Requestors: roman.daniel [...] davosro.cz
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: (no value)
Fixed in: (no value)



Subject: pairmap lexical vars inside coderef
MIME-Version: 1.0
X-Mailer: MIME-tools 5.504 (Entity 5.504)
Content-Disposition: inline
X-RT-Interface: Web
Message-ID: <rt-4.0.18-23447-1399392098-322.0-0-0 [...] rt.cpan.org>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: binary
X-RT-Original-Encoding: utf-8
X-RT-Encrypt: 0
X-RT-Sign: 0
Content-Length: 713
Download (untitled) / with headers
text/plain 713b
Running pairmap the variables inside anonymous sub "are not created" for each iteration as I would expected. Better with example: use strict; use warnings; use List::Util qw(pairmap); my @subs = pairmap { my $v = "$a,$b"; sub {$v}; } one => 'ONE', two => 'TWO', three => 'THREE'; warn $_->(),"\n" for @subs; This example displays three,THREE three,THREE three,THREE while I would expect one,ONE two,TWO three,THREE Is there any simple explanation for such behaviour (I admit it is probably not a typical usage of pairmap). Similar example with map works as I expect: my @subs = map { my $v = $_; sub {$v}; } 'one','two','three'; warn $_->(),"\n" for @subs; displays one two three
MIME-Version: 1.0
In-Reply-To: <rt-4.0.18-23447-1399392098-322.0-0-0 [...] rt.cpan.org>
X-Mailer: MIME-tools 5.504 (Entity 5.504)
Content-Disposition: inline
X-RT-Interface: Web
References: <rt-4.0.18-23447-1399392098-322.0-0-0 [...] rt.cpan.org>
Content-Type: text/plain; charset="utf-8"
Message-ID: <rt-4.0.18-30509-1400086574-1728.95409-0-0 [...] rt.cpan.org>
Content-Transfer-Encoding: binary
X-RT-Original-Encoding: utf-8
X-RT-Encrypt: 0
X-RT-Sign: 0
Content-Length: 827
Download (untitled) / with headers
text/plain 827b
On Tue May 06 12:01:38 2014, DANIELR wrote: Show quoted text
> Running pairmap the variables inside anonymous sub "are not created" > for each iteration as I would expected. Better with example: > > use strict; > use warnings; > use List::Util qw(pairmap); > > my @subs = pairmap { > my $v = "$a,$b"; > sub {$v}; > } > one => 'ONE', two => 'TWO', three => 'THREE'; > > warn $_->(),"\n" for @subs; > > This example displays > > three,THREE > three,THREE > three,THREE
Indeed it does; I can reproduce that here. That is most odd. At first consideration, I suspect a side-effect of the MULTICALL setup used to run the actual code block. map {} being an internal operator that takes a real expression rather just a CODE reference means it doesn't have to rely on MULTICALL to get the same lack-of-overhead around it. -- Paul Evans
MIME-Version: 1.0
In-Reply-To: <rt-4.0.18-30509-1400086574-1728.95409-0-0 [...] rt.cpan.org>
X-Mailer: MIME-tools 5.504 (Entity 5.504)
Content-Disposition: inline
X-RT-Interface: Web
References: <rt-4.0.18-23447-1399392098-322.0-0-0 [...] rt.cpan.org> <rt-4.0.18-30509-1400086574-1728.95409-0-0 [...] rt.cpan.org>
Content-Type: text/plain; charset="utf-8"
Message-ID: <rt-4.0.18-14269-1400086687-1449.95409-0-0 [...] rt.cpan.org>
Content-Transfer-Encoding: binary
X-RT-Original-Encoding: utf-8
X-RT-Encrypt: 0
X-RT-Sign: 0
Content-Length: 728
Download (untitled) / with headers
text/plain 728b
As a workaround, I can suggest wrapping the code block in a second set of {} braces, to make a new block that -will- get ENTER/LEAVEd each time the outer one is called: $ perl -MList::Util=pairmap -E 'say $_->() for pairmap { my $v = "$a,$b"; sub {$v} } one => "ONE", two => "TWO", three => "THREE"' three,THREE three,THREE three,THREE $ perl -MList::Util=pairmap -E 'say $_->() for pairmap { { my $v = "$a,$b"; sub {$v} } } one => "ONE", two => "TWO", three => "THREE"' one,ONE two,TWO three,THREE Offhand I'm afraid I can't really think of a good way to have this detected at runtime to disable the MULTICALL optimisation, without effectively having as much overhead to detect it as MULTICALL itself saves. -- Paul Evans
MIME-Version: 1.0
In-Reply-To: <rt-4.0.18-14269-1400086687-1449.95409-0-0 [...] rt.cpan.org>
X-Mailer: MIME-tools 5.504 (Entity 5.504)
Content-Disposition: inline
X-RT-Interface: Web
References: <rt-4.0.18-23447-1399392098-322.0-0-0 [...] rt.cpan.org> <rt-4.0.18-30509-1400086574-1728.95409-0-0 [...] rt.cpan.org> <rt-4.0.18-14269-1400086687-1449.95409-0-0 [...] rt.cpan.org>
Content-Type: text/plain; charset="utf-8"
Message-ID: <rt-4.0.18-5155-1401978149-283.95409-0-0 [...] rt.cpan.org>
Content-Transfer-Encoding: binary
X-RT-Original-Encoding: utf-8
X-RT-Encrypt: 0
X-RT-Sign: 0
Content-Length: 678
Download (untitled) / with headers
text/plain 678b
As currently I don't have a good solution to this bug, I will at least document it in the KNOWN BUGS section, along with the double-brace workaround so people will know how to work around it. I think a proper solution may involve looking at the SvREFCNT of every SV in the block's pad. Clearly if every SV has refcount 0 then we're safe to use MULTICALL, but I wonder if that's overkill. A finer-grained solution would be to compare before/after counts and stop doing MULTICALL the moment any refcount gets increased, but it would have to be carefully benchmarked to see if that's actually any quicker than just not bothering with MULTICALL in the first place. -- Paul Evans
MIME-Version: 1.0
In-Reply-To: <rt-4.0.18-5155-1401978149-283.95409-0-0 [...] rt.cpan.org>
X-Mailer: MIME-tools 5.504 (Entity 5.504)
Content-Disposition: inline
X-RT-Interface: Web
References: <rt-4.0.18-23447-1399392098-322.0-0-0 [...] rt.cpan.org> <rt-4.0.18-30509-1400086574-1728.95409-0-0 [...] rt.cpan.org> <rt-4.0.18-14269-1400086687-1449.95409-0-0 [...] rt.cpan.org> <rt-4.0.18-5155-1401978149-283.95409-0-0 [...] rt.cpan.org>
Content-Type: text/plain; charset="utf-8"
Message-ID: <rt-4.0.18-29927-1406563191-698.95409-0-0 [...] rt.cpan.org>
Content-Transfer-Encoding: binary
X-RT-Original-Encoding: utf-8
X-RT-Encrypt: 0
X-RT-Sign: 0
Content-Length: 909
Download (untitled) / with headers
text/plain 909b
On Thu Jun 05 10:22:29 2014, PEVANS wrote: Show quoted text
> As currently I don't have a good solution to this bug, I will at least > document it in the KNOWN BUGS section, along with the double-brace > workaround so people will know how to work around it.
May be there should be noted in KNOWN BUGS section that the problem with lexicals is not limited to a returned closure but probably occurs with any reference to a lexical variable. We were recently got bitten with something like this. use strict; use List::Util qw(pairmap); use Data::Dumper; warn Dumper([ pairmap { my @h = ( $a, $b ); \@h; } a => 1, b => 2, c => 3 ]); which yields $VAR1 = [ [ 'c', 3 ], $VAR1->[0], $VAR1->[0] ]; I do not know anything about Perl internals but is the MULTICALL optimization speedup really worth all the explanations?
MIME-Version: 1.0
In-Reply-To: <rt-4.0.18-5155-1401978149-283.95409-0-0 [...] rt.cpan.org>
X-Mailer: MIME-tools 5.504 (Entity 5.504)
Content-Disposition: inline
X-RT-Interface: Web
References: <rt-4.0.18-23447-1399392098-322.0-0-0 [...] rt.cpan.org> <rt-4.0.18-30509-1400086574-1728.95409-0-0 [...] rt.cpan.org> <rt-4.0.18-14269-1400086687-1449.95409-0-0 [...] rt.cpan.org> <rt-4.0.18-5155-1401978149-283.95409-0-0 [...] rt.cpan.org>
Content-Type: text/plain; charset="utf-8"
Message-ID: <rt-4.0.18-26337-1406807055-936.95409-0-0 [...] rt.cpan.org>
Content-Transfer-Encoding: binary
X-RT-Original-Encoding: utf-8
X-RT-Encrypt: 0
X-RT-Sign: 0
Content-Length: 918
Download (untitled) / with headers
text/plain 918b
On Thu Jun 05 10:22:29 2014, PEVANS wrote: Show quoted text
> As currently I don't have a good solution to this bug, I will at least > document it in the KNOWN BUGS section, along with the double-brace > workaround so people will know how to work around it. >
I guess that also reduce is affected as the function collecting the returned value: use strict; use List::Util qw(reduce); use Data::Dumper; sub myreduce(&@) { my ($code, $result) = (shift(), shift()); while (@_) { ( $a, $b ) = ( $result, shift() ); $result = $code->(); } return $result; } warn Dumper( reduce { my @ary = ( $a, $b ); \@ary; } qw(a b c ) ); warn Dumper( myreduce { my @ary = ( $a, $b ); \@ary; } qw(a b c ) ); which yields $VAR1 = [ $VAR1, 'c' ]; $VAR1 = [ [ 'a', 'b' ], 'c' ];


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.