Skip Menu |

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

Report information
The Basics
Id: 77595
Status: rejected
Priority: 0/
Queue: Scalar-List-Utils

People
Owner: Nobody in particular
Requestors: KOORCHIK [...] cpan.org
Cc:
AdminCc:

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



Subject: List::Util::first does not localize $_ in given/when statement
See attached file with test
Subject: list_util_bug.pl
use List::Util qw/first/; use v5.10; use Test::More; is( test('grep'), 4, 'Grep for finding first value' ); is( test('list util'), 4, 'List::Util::first for finding first value' ); sub test { my $mode = shift; my @array = (1..10); given ($mode) { when ('list_util') { my $first = first { $_ == 4 } @array; return $first; } when ('grep') { my ($first) = grep { $_ == 4 } @array; return $first } } } done_testing;
Суб Июн 02 07:37:22 2012, KOORCHIK писал: Show quoted text
> See attached file with test
See the test with fixed typo
Subject: list_util_bug.pl
use List::Util qw/first/; use v5.10; use Test::More; is( test('grep'), 4, 'Grep for finding first value' ); is( test('list_util'), 4, 'List::Util::first for finding first value' ); sub test { my $mode = shift; my @array = (1..10); given ($mode) { when ('list_util') { my $first = first { $_ == 4 } @array; return $first; } when ('grep') { my ($first) = grep { $_ == 4 } @array; return $first } default { die "wrong test"; } } } done_testing;
Subject: Re: [rt.cpan.org #77595] List::Util::first does not localize $_ in given/when statement
Date: Mon, 4 Jun 2012 17:17:41 -0500
To: bug-Scalar-List-Utils [...] rt.cpan.org
From: Graham Barr <gbarr [...] pobox.com>
On Jun 2, 2012, at 06:47 , Viktor Tuskyi via RT wrote: This is because when given was implemented it was decided to make it create a lexical $_ instead of the package $_ like every other construct before it. As such the sub passed as the first argument to first has $_ bound to the lexical $_ from given not the package $_ that first will be assigning to. adding our $_; inside the block passed to first should work around this. Graham. Show quoted text
> See the test with fixed typo > use List::Util qw/first/; > use v5.10; > use Test::More; > > is( test('grep'), 4, 'Grep for finding first value' ); > is( test('list_util'), 4, 'List::Util::first for finding first value' ); > > > sub test { > my $mode = shift; > my @array = (1..10); > > given ($mode) { > when ('list_util') { > my $first = first { $_ == 4 } @array; > return $first; > } > when ('grep') { > my ($first) = grep { $_ == 4 } @array; > return $first > } > default { > die "wrong test"; > } > } > } > > done_testing;
Thank you. It was a surprise for me that "given" creates own lexical variable "$_", strange implementation. So, it is not safe to define closures in given/when. Also, there is one more possible solution - to use "for" instead of "given" for ($var) { when ("value") { } default { } }
As this is basically just perl's "given" working oddly and lexicalising $_, I'm going to close this bug. Feel free to re-open it if you feel this inappropriate. -- Paul Evans