Skip Menu |
Report information
Id: 77510
Status: open
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: comdog <brian.d.foy [at] gmail.com>
Cc:
AdminCc:

Operating System: darwin
PatchStatus: (no value)
Severity: medium
Type: core
Perl Version: 5.12.1
Fixed In: (no value)



Subject: when() as a statement modifier outside a topicalizer both works and fails
Date: Mon, 30 Aug 2010 01:29:09 -0400
To: perlbug [...] perl.org
From: brian d foy <brian.d.foy [...] gmail.com>
Download (untitled) / with headers
text/plain 4.3k
This is a bug report for perl from brian.d.foy@gmail.com, generated with the help of perlbug 1.39 running under perl 5.12.1. ----------------------------------------------------------------- [Please describe your issue here] Perl 5.12 allows when() as a statement modifier. I think this is only intended inside a topicalizer, but it parses just fine outside a topicalizer. This script compiles just fine: use 5.012; my %microchips = ( 'Mimi' => 123, 'Buster' => undef, 'Roscoe' => 345, ); say "Known cats are @{[keys %microchips]}\n"; { print "Enter a cat name> "; chomp( $_ = <STDIN> ); say "Found cat with id $microchips{$_}" when %microchips; redo; } Now, when I run this and respond to a prompt with a cat's name that is in the hash, the say() outputs its message and Perl dies: Buster Found cat with id Can't use when() outside a topicalizer at test line 11, <STDIN> line That's fine, but I don't get the same error when I respond with a cat's name that is not in the hash: Enter a cat name> Ella Enter a cat name> Buster Found cat with id Can't use when() outside a topicalizer at test line 12, <STDIN> line 2. That is, the when() always works. If its condition is true, it also dies. If its condition is false, it does not die. I verified this with all released versions of 5.12 and 5.13. I figure this should be a compile-time error, or, if we're really lazy, just never die. [Please do not change anything below this line] ----------------------------------------------------------------- --- Flags: category=core severity=medium --- Site configuration information for perl 5.12.1: Configured by brian at Wed Jun 16 15:54:54 PDT 2010. Summary of my perl5 (revision 5 version 12 subversion 1) configuration: Platform: osname=darwin, osvers=9.8.0, archname=darwin-2level uname='darwin mimibean.local 9.8.0 darwin kernel version 9.8.0: wed jul 15 16:55:01 pdt 2009; root:xnu-1228.15.4~1release_i386 i386 i386 ' config_args='-des -Dprefix=/usr/local/perls/perl-5.12.1' hint=recommended, useposix=true, d_sigaction=define useithreads=undef, usemultiplicity=undef useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef use64bitint=undef, use64bitall=undef, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include', optimize='-O3', cppflags='-no-cpp-precomp -fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion='', gccversion='4.0.1 (Apple Inc. build 5490)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -fstack-protector -L/usr/local/lib' libpth=/usr/local/lib /usr/lib libs=-ldbm -ldl -lm -lutil -lc perllibs=-ldl -lm -lutil -lc libc=/usr/lib/libc.dylib, so=dylib, useshrplib=false, libperl=libperl.a gnulibc_version='' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' ' cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector' Locally applied patches: --- @INC for perl 5.12.1: /usr/local/perls/perl-5.12.1/lib/site_perl/5.12.1/darwin-2level /usr/local/perls/perl-5.12.1/lib/site_perl/5.12.1 /usr/local/perls/perl-5.12.1/lib/5.12.1/darwin-2level /usr/local/perls/perl-5.12.1/lib/5.12.1 . --- Environment for perl 5.12.1: DYLD_LIBRARY_PATH (unset) HOME=/Users/brian LANG=en_US LANGUAGE (unset) LC_ALL=C LC_COLLATE=en_US.UTF-8 LC_CTYPE=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_MONETARY=en_US.UTF-8 LC_NUMERIC=en_US.UTF-8 LC_TIME=en_US.UTF-8 LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/Users/brian/bin:/usr/local/bin:/opt/local/bin:/Users/brian/TPR/scripts:/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/mysql/bin:/usr/X11R6/bin:/usr/local/teTeX/bin/powerpc-apple-darwin-current:/usr/local/pgsql/bin:/usr/local/gcj/bin:/Library/Frameworks/Python.framework/Versions/Current/bin PERL_BADLANG (unset) SHELL=/bin/bash
Subject: Re: [perl #77510] when() as a statement modifier outside a topicalizer both works and fails
Date: Mon, 30 Aug 2010 10:25:24 +0200
To: perl5-porters [...] perl.org
From: Vincent Pit <perl [...] profvince.com>
Download (untitled) / with headers
text/plain 1.4k
Show quoted text
> Perl 5.12 allows when() as a statement modifier. I think this > is only intended inside a topicalizer, but it parses just > fine outside a topicalizer. > > ... > > That is, the when() always works. If its condition is true, it also dies. If > its condition is false, it does not die.
Thanks for your report. The same behaviour happens if "when" isn't a statement modifier : $ perl -wE '$_ = "abc"; { when (/x/) { say "contains x" }; when (/b/) { say "contains b" }; say "end" }' contains b Can't use when() outside a topicalizer at -e line 1. $ perl -wE '$_ = "abc"; { say "contains x" when /x/; say "contains b" when /b/; say "end" }' contains b Can't use when() outside a topicalizer at -e line 1. Show quoted text
> I verified this with all released versions of 5.12 and 5.13. > > I figure this should be a compile-time error, or, if we're really lazy, just > never die.
I don't think we can make it a compile time error, because you don't always know at compile time if "when" is inside a for or a given block : $ perl -wE 'sub check { my $x = shift; say "contains $x" when /$x/ } $_ = "abc"; { check("x"); check("b"); say "end" }' contains b Can't use when() outside a topicalizer at -e line 1. $ perl -wE 'sub check { my $x = shift; when (/$x/) { say "contains $x" } } $_ = "abc"; { check("x"); check("b"); say "end" }' contains b Can't use when() outside a topicalizer at -e line 1. Vincent.
Subject: Re: [perl #77510] when() as a statement modifier outside a topicalizer both works and fails
Date: Mon, 30 Aug 2010 17:17:55 -0400
To: perl5-porters [...] perl.org
From: brian d foy <brian.d.foy [...] gmail.com>
Download (untitled) / with headers
text/plain 709b
In article <4C7B6AF4.7000207@profvince.com>, Vincent Pit <perl@profvince.com> wrote: Show quoted text
> > I verified this with all released versions of 5.12 and 5.13. > > > > I figure this should be a compile-time error, or, if we're really lazy, just > > never die.
Show quoted text
> I don't think we can make it a compile time error, because you don't > always know at compile time if "when" is inside a for or a given block :
I don't see how your examples illustrate that, but I don't think that calling a subroutine that contains a when() should qualify as "inside a topicalizer" because you call the subroutine inside a topicalizer. I'm not sure why you'd even try to do that since the topic shouldn't be visible in the subroutine.
CC: brian d foy <brian.d.foy [...] gmail.com>
Subject: Re: [perl #77510] when() as a statement modifier outside a topicalizer both works and fails
Date: Tue, 31 Aug 2010 00:14:48 +0200
To: The Perl5 Porters Mailing List <perl5-porters [...] perl.org>
From: Vincent Pit <perl [...] profvince.com>
Download (untitled) / with headers
text/plain 1.2k
Show quoted text
>> I don't think we can make it a compile time error, because you don't >> always know at compile time if "when" is inside a for or a given block :
> I don't see how your examples illustrate that,
Because at the moment the sub is compiled, it is of course apparently not inside any for/given block. Yet it can be called at run-time while inside one of these and this is prefectly correct. Show quoted text
> but I don't think that > calling a subroutine that contains a when() should qualify as "inside a > topicalizer" because you call the subroutine inside a topicalizer. I'm > not sure why you'd even try to do that since the topic shouldn't be > visible in the subroutine
Not with given, as it lexicalises $_, but for loops only localises the global $_. This is what allows for example the nifty syntax of using when() inside Try::Tiny's catch blocks. Although it is valid, I'll agree that it is kind of misleading of calling when() inside given() but not in the same lexical scope, because when() picks up the global $_ : $ perl -wE 'sub check { say "fail" when /x/ } $_ = "xyz"; for ("abc") { check(); } say "end"' end $ perl -wE 'sub check { say "fail" when /x/ } $_ = "xyz"; given ("abc") { check(); } say "end"' fail end Vincent.
RT-Send-CC: perl5-porters [...] perl.org
Download (untitled) / with headers
text/plain 2.1k
On Sun Aug 29 22:29:58 2010, comdog wrote: Show quoted text
> This is a bug report for perl from brian.d.foy@gmail.com, > generated with the help of perlbug 1.39 running under perl 5.12.1. > > > ----------------------------------------------------------------- > [Please describe your issue here] > > Perl 5.12 allows when() as a statement modifier. I think this > is only intended inside a topicalizer, but it parses just > fine outside a topicalizer. > > This script compiles just fine: > > use 5.012; > > my %microchips = ( > 'Mimi' => 123, > 'Buster' => undef, > 'Roscoe' => 345, > ); > > say "Known cats are @{[keys %microchips]}\n"; > { > print "Enter a cat name> "; > chomp( $_ = <STDIN> ); > say "Found cat with id $microchips{$_}" when %microchips; > redo; > } > > Now, when I run this and respond to a prompt with a cat's name > that is in the hash, the say() outputs its message and Perl > dies: > > Buster > Found cat with id > Can't use when() outside a topicalizer at test line 11, <STDIN> line > > That's fine, but I don't get the same error when I respond with > a cat's name that is not in the hash: > > Enter a cat name> Ella > Enter a cat name> Buster > Found cat with id > Can't use when() outside a topicalizer at test line 12, <STDIN> line > 2. > > That is, the when() always works. If its condition is true, it also > dies. If > its condition is false, it does not die. > > I verified this with all released versions of 5.12 and 5.13. > > I figure this should be a compile-time error, or, if we're really > lazy, just > never die.
Clarifying the error message might help. If we make it clear that ‘when’ is having trouble *exiting* a topicalizer, I think that would be good enough. But I can’t find a good way of wording it. We currently have: Can't "when" outside a topicalizer But it should be more like: "when" can't break outside a topicalizer But ‘break outside’ could be misconstrued as ‘break out of’. Maybe: "when" can't break without a topicalizer (The archaistic could make the same argument about that one.) "when" can't find a topicalizer to exit "when" can't break except from inside a topicalizer -- Father Chrysostomos
CC: perl5-porters [...] perl.org
Subject: Re: [perl #77510] when() as a statement modifier outside a topicalizer both works and fails
Date: Sun, 21 Jul 2013 16:27:59 -0400
To: Father Chrysostomos via RT <perlbug-followup [...] perl.org>
From: Ricardo Signes <perl.p5p [...] rjbs.manxome.org>
Download (untitled) / with headers
text/plain 155b
* Father Chrysostomos via RT <perlbug-followup@perl.org> [2012-08-19T15:07:16] Show quoted text
> "when" can't find a topicalizer to exit
FWIW, I like this one. -- rjbs
Download signature.asc
application/pgp-signature 490b

Message body not shown because it is not plain text.



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

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org