Skip Menu |

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

Report information
The Basics
Id: 46754
Status: rejected
Priority: 0/
Queue: List-MoreUtils

People
Owner: Nobody in particular
Requestors: paul.a.liebert [...] hp.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.22
Fixed in: (no value)



Subject: any() attaches to the wrong $_ inside a given(){ when(){ }}
The given() and when() constructs added in Perl5.10 appear to mess with $_ such that List::MoreUtils::any(), and presumably the others (all(), none() and notall()) do not function correctly. This code is a snippet from the attached file. It prints "any() broken" ----- $val = 1; given( $val ){ when(1) { say 'any() ' . (( any{ 14 == $_ } 10..15) ? 'works' : 'broken' ); } } ------ List::MoreUtils 0.22 This is perl, v5.10.0 built for i686-linux Linux lxcvipal.cv.hp.com 2.6.9-78.0.8.ELsmp #1 SMP Wed Nov 5 07:14:58 EST 2008 x86_64 x86_64 x86_64 GNU/Linux Sorry, no patch!
Subject: mua
Download mua
application/octet-stream 330b

Message body not shown because it is not plain text.

On Mon Jun 08 18:45:35 2009, paauull wrote: Show quoted text
> The given() and when() constructs added in Perl5.10 appear to mess with > $_ such that List::MoreUtils::any(), and presumably the others (all(), > none() and notall()) do not function correctly. This code is a snippet > from the attached file. It prints "any() broken" > > ----- > > $val = 1; > given( $val ){ > when(1) { > say 'any() ' . (( any{ 14 == $_ } 10..15) ? 'works' : 'broken' ); > } > }
I can confirm that this is broken. List::Util which is a core module has the same problem so I'll report this as a bug to perl5-porters. Show quoted text
> ------ > List::MoreUtils 0.22 > This is perl, v5.10.0 built for i686-linux > Linux lxcvipal.cv.hp.com 2.6.9-78.0.8.ELsmp #1 SMP Wed Nov 5 07:14:58 > EST 2008 x86_64 x86_64 x86_64 GNU/Linux > > Sorry, no patch!
This could be an issue with perl itself. The given/when thing must be doing something goofy with $_. Cheers, Tassilo
On Sun Jul 19 08:10:15 2009, VPARSEVAL wrote: Show quoted text
> On Mon Jun 08 18:45:35 2009, paauull wrote:
> > The given() and when() constructs added in Perl5.10 appear to mess with > > $_ such that List::MoreUtils::any(), and presumably the others (all(), > > none() and notall()) do not function correctly. This code is a snippet > > from the attached file. It prints "any() broken" > > > > ----- > > > > $val = 1; > > given( $val ){ > > when(1) { > > say 'any() ' . (( any{ 14 == $_ } 10..15) ? 'works' : 'broken' ); > > } > > }
> > I can confirm that this is broken. List::Util which is a core module has > the same problem so I'll report this as a bug to perl5-porters. >
> > ------ > > List::MoreUtils 0.22 > > This is perl, v5.10.0 built for i686-linux > > Linux lxcvipal.cv.hp.com 2.6.9-78.0.8.ELsmp #1 SMP Wed Nov 5 07:14:58 > > EST 2008 x86_64 x86_64 x86_64 GNU/Linux > > > > Sorry, no patch!
> > This could be an issue with perl itself. The given/when thing must be > doing something goofy with $_. > > Cheers, > Tassilo >
Subject: given_when_mucks_with_dollar_underbar.pl
#! /usr/bin/perl # Test case for bug... # https://rt.cpan.org/Ticket/Display.html?id=46754 use 5.010; use List::MoreUtils qw(any); $val = 1; given( $val ){ when(1) { say 'any() ' . (( any{ 14 == $_ } 10..15) ? 'works' : 'broken' ); } }
On Mon Jun 08 18:45:35 2009, paauull wrote: Show quoted text
> The given() and when() constructs added in Perl5.10 appear to mess with > $_ such that List::MoreUtils::any(), and presumably the others (all(), > none() and notall()) do not function correctly. This code is a snippet > from the attached file. It prints "any() broken"
As well it is expected. See below. Show quoted text
> $val = 1; > given( $val ){ > when(1) { > say 'any() ' . (( any{ 14 == $_ } 10..15) ? 'works' : 'broken' ); > } > }
given() creates a lexical variable, called $_, which is visible in the scope of the controlled block. This is a lexical variable, not a global one. Because it is lexical, the $_ that appears in any()'s control block sees this variable, and not the global one. any() can only see the global one, not the lexical one. Consider it as if the code were written instead: given( my $dollarsmudge = $val ) { when(1) { say 'any() ' . (( any{ 14 == $dollarsmudge } 10..15) ? 'works' : 'broken' ); } } This is fundamental to the way given/when work, and is not something that can be changed. -- Paul Evans
From: paul.a.liebert [...] hp.com
On Mon Jul 25 13:34:12 2011, PEVANS wrote: Show quoted text
> On Mon Jun 08 18:45:35 2009, paauull wrote:
> > The given() and when() constructs added in Perl5.10 appear to mess
> with
> > $_ such that List::MoreUtils::any(), and presumably the others
> (all(),
> > none() and notall()) do not function correctly. This code is a
> snippet
> > from the attached file. It prints "any() broken"
> > As well it is expected. See below. >
> > $val = 1; > > given( $val ){ > > when(1) { > > say 'any() ' . (( any{ 14 == $_ } 10..15) ? 'works' : 'broken'
> );
> > } > > }
> > given() creates a lexical variable, called $_, which is visible in the > scope of the controlled block. This > is a lexical variable, not a global one. Because it is lexical, the $_ > that appears in any()'s control > block sees this variable, and not the global one. any() can only see > the global one, not the lexical one. > Consider it as if the code were written instead: > > given( my $dollarsmudge = $val ) { > when(1) { > say 'any() ' . (( any{ 14 == $dollarsmudge } 10..15) ? 'works' : > 'broken' ); > } > } > > This is fundamental to the way given/when work, and is not something > that can be changed.
I believe you will find that grep() behaves correctly i.e. #!/usr/bin/env perl use warnings; use strict; use 5.010; use List::MoreUtils qw(any); my $f=1; given( $f ) { when( 1 ) { say( ( any{$_==14}(10..15)) ? "any() works" : "any() broken"); say( ( grep{$_==14}(10..15)) ? "grep() works" : "grep() broken"); } } Running the above reports "any() broken" and "grep() works". My position is that the coderef arg to any/grep is a tighter scope and therefore usurps the lexical imposed by given().
From: John Harrison
On Mon Jul 25 14:03:35 2011, paauull wrote: Show quoted text
> On Mon Jul 25 13:34:12 2011, PEVANS wrote:
> > On Mon Jun 08 18:45:35 2009, paauull wrote:
> > > The given() and when() constructs added in Perl5.10 appear to mess
> > with
> > > $_ such that List::MoreUtils::any(), and presumably the others
> > (all(),
> > > none() and notall()) do not function correctly. This code is a
> > snippet
> > > from the attached file. It prints "any() broken"
> > > > As well it is expected. See below. > >
> > > $val = 1; > > > given( $val ){ > > > when(1) { > > > say 'any() ' . (( any{ 14 == $_ } 10..15) ? 'works' : 'broken'
> > );
> > > } > > > }
> > > > given() creates a lexical variable, called $_, which is visible in the > > scope of the controlled block. This > > is a lexical variable, not a global one. Because it is lexical, the $_ > > that appears in any()'s control > > block sees this variable, and not the global one. any() can only see > > the global one, not the lexical one. > > Consider it as if the code were written instead: > > > > given( my $dollarsmudge = $val ) { > > when(1) { > > say 'any() ' . (( any{ 14 == $dollarsmudge } 10..15) ? 'works' : > > 'broken' ); > > } > > } > > > > This is fundamental to the way given/when work, and is not something > > that can be changed.
> > > I believe you will find that grep() behaves correctly i.e. > > #!/usr/bin/env perl > use warnings; > use strict; > use 5.010; > > use List::MoreUtils qw(any); > > my $f=1; > given( $f ) { > when( 1 ) { > > say( ( any{$_==14}(10..15)) ? "any() works" : "any() > broken"); > say( ( grep{$_==14}(10..15)) ? "grep() works" : "grep() > broken"); > } > } > > Running the above reports "any() broken" and "grep() works". My > position is that the coderef arg to any/grep is a tighter scope and > therefore usurps the lexical imposed by given().
Expanding this test a bit further, it seems inconsistant between for and given: use v5.14; use List::MoreUtils qw/any/; my $f=1; say 'bare'; say(( any { $_ == 14} (10..15)) ? "any() works" : "any() broken"); say((grep { $_ == 14} (10..15)) ? "grep() works" : "grep() broken"); for ($f) { say "\nfor"; say(( any { $_ == 14} (10..15)) ? "any() works" : "any() broken"); say((grep { $_ == 14} (10..15)) ? "grep() works" : "grep() broken"); when( 1 ) { say(( any { $_ == 14} (10..15)) ? "any() works" : "any() broken"); say((grep { $_ == 14} (10..15)) ? "grep() works" : "grep() broken"); say 'done'; } } given ($f) { say "\ngiven"; say(( any { $_ == 14} (10..15)) ? "any() works" : "any() broken"); say((grep { $_ == 14} (10..15)) ? "grep() works" : "grep() broken"); when( 1 ) { say(( any { $_ == 14} (10..15)) ? "any() works" : "any() broken"); say((grep { $_ == 14} (10..15)) ? "grep() works" : "grep() broken"); } }
as noted in comment on Blogs.perl.org Here's a work-around. A bit ugly but ... when(1) { say $_ if any {our $_; $_ == 2} (2,3)} The Anonymous function can specify that it's not a closure over the implicit lexical $_ of given but rather is using global $_ by declaring it our $_;. Maybe we need to propose doc fixes to the impacted List::* modules' POD to give this workaround. [ The alternative I can think of is for the any() etc functions to be made magic like grep. Maybe a B::* using utility subr could munge the optree to switch lexical $_ refs to global in the block arg. Would want it to only do that once for any given block. Would be easier with Perl6 AST edits! ]
This issue itself is found in the behavior of given/when. Consider using experimental features only when fully understand the impact.