Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.96k stars 555 forks source link

more given nonsense: what's a topicalizer? #11327

Open p5pRT opened 13 years ago

p5pRT commented 13 years ago

Migrated from rt.perl.org#90182 (status was 'open')

Searchable as RT90182$

p5pRT commented 13 years ago

From tchrist@perl.com

When you run this​:

  use 5.010;   while (\) {   when (/foo/) { say "meta" }   when (/\d/) { say "number" }   default { say "other" }   }   __END__   fee fie   23 skiddoo   foo fum

You get​:

  other   Can't use when() outside a topicalizer at /tmp/s0 line 5\, \ line 1.   Exit 255

In other words\, it does the right thing\, and then blows up.
The work around is​:

  use 5.010;   while (\) {   eval { # ...protect the loop from senseless nannying   when (/foo/) { say "meta" }   when (/\d/) { say "number" }   default { say "other" }   }   }   __END__   fee fie   23 skiddoo   foo fum

Which correctly prints​:

  other   number   meta

which is just ridiculous. What does it think

  while (\)

is if not a topicalizer??

BTW\, this *does* work correctly in Perl 6.

--tom

Summary of my perl5 (revision 5 version 12 subversion 3) configuration​:  
  Platform​:   osname=openbsd\, osvers=4.4\, archname=OpenBSD.i386-openbsd   uname='openbsd chthon 4.4 generic#0 i386 '   config_args='-des'   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-strict-aliasing -pipe -fstack-protector -I/usr/local/include'\,   optimize='-O2'\,   cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'   ccversion=''\, gccversion='3.3.5 (propolice)'\, gccosandvers='openbsd4.4'   intsize=4\, longsize=4\, ptrsize=4\, doublesize=8\, byteorder=1234   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=12   ivtype='long'\, ivsize=4\, nvtype='double'\, nvsize=8\, Off_t='off_t'\, lseeksize=8   alignbytes=4\, prototype=define   Linker and Libraries​:   ld='cc'\, ldflags ='-Wl\,-E -fstack-protector -L/usr/local/lib'   libpth=/usr/local/lib /usr/lib   libs=-lgdbm -lm -lutil -lc   perllibs=-lm -lutil -lc   libc=/usr/lib/libc.so.48.0\, so=so\, useshrplib=false\, libperl=libperl.a   gnulibc_version=''   Dynamic Linking​:   dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags=' '   cccdlflags='-DPIC -fPIC '\, lddlflags='-shared -fPIC -L/usr/local/lib -fstack-protector'

Characteristics of this binary (from libperl)​:   Compile-time options​: PERL_DONT_CREATE_GVSV PERL_MALLOC_WRAP   USE_LARGE_FILES USE_PERLIO USE_PERL_ATOF   Built under openbsd   Compiled at Feb 14 2011 07​:32​:03   %ENV​:   PERL_UNICODE="SA"   @​INC​:   /usr/local/lib/perl5/site_perl/5.12.3/OpenBSD.i386-openbsd   /usr/local/lib/perl5/site_perl/5.12.3   /usr/local/lib/perl5/5.12.3/OpenBSD.i386-openbsd   /usr/local/lib/perl5/5.12.3   /usr/local/lib/perl5/site_perl/5.11.3   /usr/local/lib/perl5/site_perl/5.10.1   /usr/local/lib/perl5/site_perl/5.10.0   /usr/local/lib/perl5/site_perl/5.8.7   /usr/local/lib/perl5/site_perl/5.8.0   /usr/local/lib/perl5/site_perl/5.6.0   /usr/local/lib/perl5/site_perl/5.005   /usr/local/lib/perl5/site_perl   .

p5pRT commented 13 years ago

From @ikegami

On Mon\, May 9\, 2011 at 9​:50 AM\, tchrist1 \perlbug\-followup@​perl\.org wrote​:

which is just ridiculous. What does it think

while (\)

is if not a topicalizer??

So what would qualify?

while ($_ = ...) { ... } while (defined($_ = ...)) { ... } while (($_ = ...) RELOP ...) { ... } while (...\, $_ = ...\, ...) { ... } while (...\, defined($_ = ...)\, ...) { ... } while (...\, ($_ = ...) RELOP ...\, ...) { ... }

Same for C\<for(;;)>?

p5pRT commented 13 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 13 years ago

From tchrist@perl.com

"Eric Brine via RT" \perlbug\-followup@&#8203;perl\.org wrote   on Tue\, 10 May 2011 09​:41​:45 PDT​:

which is just ridiculous. What does it think

while (\)

is if not a topicalizer??

So what would qualify?

while ($_ = ...) { ... } while (defined($_ = ...)) { ... } while (($_ = ...) RELOP ...) { ... } while (...\, $_ = ...\, ...) { ... } while (...\, defined($_ = ...)\, ...) { ... } while (...\, ($_ = ...) RELOP ...\, ...) { ... }

Same for C\<for(;;)>?

In Perl6\, when works wherever $_ is around to test against. This seems perfectly straightforward. I don't know how this very complicated set of behaviors found their way into Perl5.

--tom

p5pRT commented 13 years ago

From @ikegami

In Perl6\, when works wherever $_ is around to test against.

$_ is always around in Perl5\, even when there's nothing to next/break out of.

p5pRT commented 13 years ago

From tchrist@perl.com

Eric Brine \ikegami@&#8203;adaelis\.com wrote   on Tue\, 10 May 2011 13​:01​:44 EDT​:

In Perl6\, when works wherever $_ is around to test against.

$_ is always around in Perl5\, even when there's nothing to next/break out of.

Just let them try. :)

I would be quite happy to have it in

  while (\<>) {   ... when ...;   ... when ...;   ... when ...;   ... when ...;   }

--tom

p5pRT commented 13 years ago

From @ap

* tchrist1 \perlbug\-followup@&#8203;perl\.org [2011-05-09 15​:55]​:

which is just ridiculous. What does it think

while \(\<DATA>\)

is if not a topicalizer??

BTW\, this *does* work correctly in Perl 6.

I think this is the consequence of `break` being added as a `given`-specific special form of `next`. I am guessing wildly that the thought behind adding `break` was that doing `next` inside `given` should abort the iteration of a surrounding loop instead of just the `given` block\, maybe in (mistaken) analogy to what `next` does inside `if`. At least that is the only plausible reason I can imagine why someone thought `break` was a good idea.

And once you have `break` you have to come up with a special set of rules for how `when` will examine scope\, which gets you into this mess.

Needless to say I don’t see the point since it’s possible to do `next LABEL` and this is how one has always been supposed to break out of nested loops. Half amusing and half maddening is that `given` has *extra* special rules to do `next` instead of `break` when inside a `foreach` rather than a `given`.

I think `when` shouldn’t just do an implicit `next` in all cases. That already has clear rules about what it will complain of\, and it would make `when` far more useful.

In fact if `when` lost the implicit smart match and became *nothing else/more* than an `if` with implicit `next`\, I’d find it *even better*. That’s probably not feasible\, alas. But we could at least lose this `break` silliness.

Regards\, -- Aristotle Pagaltzis // \<http​://plasmasturm.org/>

p5pRT commented 13 years ago

From @ikegami

On Tue\, May 10\, 2011 at 3​:10 PM\, Tom Christiansen \tchrist@&#8203;perl\.com wrote​:

Eric Brine \ikegami@&#8203;adaelis\.com wrote on Tue\, 10 May 2011 13​:01​:44 EDT​:

In Perl6\, when works wherever $_ is around to test against.

$_ is always around in Perl5\, even when there's nothing to next/break out of.

Just let them try. :)

That's what's happening. It's trying to C\ and finds neither C\ or C\ (for C\).

It could start looking for any loop. Is there any problems (compatibility issues) with doing so?

p5pRT commented 13 years ago

From @ap

* Aristotle Pagaltzis \pagaltzis@&#8203;gmx\.de [2011-05-11 00​:15]​:

I think `when` shouldn’t just do an implicit `next` in all cases.

No\, I don’t think that\, I just ended up saying it because of too much editing. I think it *should* just do an implicit `next`.

Regards\, -- Aristotle Pagaltzis // \<http​://plasmasturm.org/>

p5pRT commented 13 years ago

From tchrist@perl.com

* Aristotle Pagaltzis \pagaltzis@&#8203;gmx\.de [2011-05-11 00​:15]​:

I think `when` shouldn’t just do an implicit `next` in all cases.

No\, I don’t think that\, I just ended up saying it because of too much editing. I think it *should* just do an implicit `next`.

Me\, I was surprised it didn't.

--tom

p5pRT commented 13 years ago

From @cpansprout

On Mon May 09 06​:50​:09 2011\, tom christiansen wrote​:

When you run this​:

use 5\.010;
while \(\<DATA>\) \{
when \(/foo/\) \{ say "meta"   \}
when \(/\\d/\)  \{ say "number" \}
default      \{ say "other"  \}
\}
\_\_END\_\_
fee fie
23 skiddoo
foo fum

You get​:

other
Can't use when\(\) outside a topicalizer at /tmp/s0 line 5\, \<DATA>

line 1. Exit 255

It’s even stranger than you think​:

$ perl -E 'given(1) { for my $x (2) { break } } warn ok' ok at -e line 1. $ perl -E 'given(1) { for (2) { break } }' Can't "break" in a loop topicalizer at -e line 1.

p5pRT commented 12 years ago

From perl-diddler@tlinx.org

Created by perl-diddler@tlinx.org

It seems like perl is being a bit over zealous about it's policing the use of "when". Technically\, a topicalizer is something that defines the "topic" (or subject).. like given and when automatically use '$_'. But I can write my own 'topicalizer' that funnels data into $_ -- trivially.

A prime example would be 'when(\<>){}'\, where you process lines like /filt/ and do {xxyz; continue}; /filter/ and do {xxyz+1; next}; ...

Sometimes an if/elsif/else/ construct is useful\, but only if you don't have exceptions.

Another example I ran into today​:

In a trivial prog\, I had a foreach loop to parse args.
Later had an arg that took a param -- how to skip a 'each'\, in foreach? Well​:

for ($_=$ARGV[$n = 0]; $n\<@​ARGV; $_=$ARGV[$n]) {   ...   when(arg (-rc) with param) {   my $m=$n+1;   $m>=$#ARGV or die "-rc needs param\n";   $rc=$ARGV[$m]; ++$n   }   when (next case)... }

--- Course now\, this doesn't work -- to make it work I'll have to add an extra 2 lines inside the forloop\, which I hope won't have any side effects...i.e.

for ($_=each(@​ARGV); $_\<=lastmem(@​ARGV); $_=next(@​ARGV) ) {   given ($_) {   when ...   ...   } }

Can someone explain to me the rational for the interpreter to 'restrict' the usage of 'when' to a smaller subset than where 'last/next/continue' would work or why it not working in the same places shouldn't be considered a bug?

Thanks!
(p.s. can you think of any side effects of tossing in the extra given{} in the for loop to satisfy the interp's warnings?)

Perl Info ``` Flags: category=core severity=low This perlbug was built using Perl 5.12.3 - Fri May 6 13:31:41 UTC 2011 It is being executed now by Perl 5.12.3 - Fri May 6 13:26:30 UTC 2011. Site configuration information for perl 5.12.3: Configured by abuild at Fri May 6 13:26:30 UTC 2011. Summary of my perl5 (revision 5 version 12 subversion 3) configuration: Platform: osname=linux, osvers=2.6.36, archname=x86_64-linux-thread-multi uname='linux build33 2.6.36 #1 smp 2011-02-21 10:34:10 +0100 x86_64 x86_64 x86_64 gnulinux ' config_args='-ds -e -Dprefix=/usr -Dvendorprefix=/usr -Dinstallusrbinperl -Dusethreads -Di_db -Di_dbm -Di_ndbm -Di_gdbm -Duseshrplib=true -Doptimize=-fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack- protector -funwind-tables -fasynchronous-unwind-tables -g -Wall -pipe -Accflags=-DPERL_USE_SAFE_PUTENV' hint=recommended, useposix=true, d_sigaction=define useithreads=define, usemultiplicity=define useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef use64bitint=define, use64bitall=define, uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DPERL_USE_SAFE_PUTENV -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -Wall -pipe', cppflags='-D_REENTRANT -D_GNU_SOURCE -DPERL_USE_SAFE_PUTENV -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector' ccversion='', gccversion='4.5.1 20101208 [gcc-4_5-branch revision 167585]', gccosandvers='' intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib64 -fstack-protector' libpth=/lib64 /usr/lib64 /usr/local/lib64 libs=-lm -ldl -lcrypt -lpthread perllibs=-lm -ldl -lcrypt -lpthread libc=/lib64/libc-2.11.3.so, so=so, useshrplib=true, libperl=libperl.so gnulibc_version='2.11.3' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.12.3/x86_64-linux-thread-multi/CORE' cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib64 -fstack-protector' Locally applied patches: @INC for perl 5.12.3: /usr/lib/perl5/site_perl/5.12.3/x86_64-linux-thread-multi /usr/lib/perl5/site_perl/5.12.3 /usr/lib/perl5/vendor_perl/5.12.3/x86_64-linux-thread-multi /usr/lib/perl5/vendor_perl/5.12.3 /usr/lib/perl5/5.12.3/x86_64-linux-thread-multi /usr/lib/perl5/5.12.3 . Environment for perl 5.12.3: HOME=/home/law LANG=en_US.UTF-8 LANGUAGE (unset) LC_CTYPE=en_US.UTF-8 LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=.:/sbin:/usr/local/sbin:/opt/lsb/bin:/home/law/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/games:/opt/kde3/bin:/usr/lib/mit/bin:/usr/lib/mit/sbin:/usr/lib/qt3/bin:/usr/sbin PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 12 years ago

From @ikegami

On Sun\, Jan 22\, 2012 at 12​:21 AM\, Linda Walsh \perlbug\-followup@&#8203;perl\.orgwrote​:

Can someone explain to me the rational for the interpreter to 'restrict' the usage of 'when' to a smaller subset than where 'last/next/continue' would work

C\ was primary written to compare to $_ (e.g. C\<\< when ("foo") >>)\, so it's only allowed in flow control statements that set $_ (e.g. C\<\< for (...) >>\, but not C\<\< for my $x (...) >> and C\<\< for (...; ...; ...) >>).

p5pRT commented 12 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 12 years ago

From @cpansprout

On Sat Jan 21 22​:11​:07 2012\, ikegami@​adaelis.com wrote​:

On Sun\, Jan 22\, 2012 at 12​:21 AM\, Linda Walsh \<perlbug- followup@​perl.org>wrote​:

Can someone explain to me the rational for the interpreter to 'restrict' the usage of 'when' to a smaller subset than where 'last/next/continue' would work

C\ was primary written to compare to $_ (e.g. C\<\< when ("foo")

)\, so it's only allowed in flow control statements that set $_ (e.g. C\<\< for (...) >>\, but not C\<\< for my $x (...) >> and C\<\< for (...; ...; ...) ).

Except even that doesn’t work properly. Since this is basically the same issue\, I’m merging it with #90182.

--

Father Chrysostomos

jkeenan commented 5 months ago

This program was provided by the OP who ran it against perl-5.12.3.

$ $ cat $P5P_DIR/gh-11327-topicalizer.pl
use 5.010;
# https://github.com/Perl/perl5/issues/11327
# originally: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=90182

while (<DATA>) {
    when (/foo/) { say "meta" }
    when (/\d/) { say "number" }
    default { say "other" }
}
__END__
fee fie
23 skiddoo
foo fum

The output originally reported was:

other
  Can't use when() outside a topicalizer at /tmp/s0 line 5, <DATA> line 1.
  Exit 255

Let's see what happens with later versions of Perl.

$ perlbrew use perl-5.14.4
$ perl /tmp/gh-11327-topicalizer.pl
other
Can't use when() outside a topicalizer at /tmp/gh-11327-topicalizer.pl line 8, <DATA> line 1.

$ perlbrew use perl-5.16.3
[perl] 2366 $ perl /tmp/gh-11327-topicalizer.pl
other
Can't "default" outside a topicalizer at /tmp/gh-11327-topicalizer.pl line 8, <DATA> line 1.

So the output changed between perl-5.14 and perl-5.16.

$ perlbrew use perl-5.18.4
$ perl /tmp/gh-11327-topicalizer.pl
when is experimental at /tmp/gh-11327-topicalizer.pl line 6.
when is experimental at /tmp/gh-11327-topicalizer.pl line 7.
other
Can't "default" outside a topicalizer at /tmp/gh-11327-topicalizer.pl line 8, <DATA> line 1.

A warning appeared in perl-5.18. The output above is what still appears in perl-5.38 and is scheduled to appear in perl-5.40 as well.

Given that the smartmatch given/when syntax will be removed from the language after the release of perl-5.40, s there any reason to keep this 13-year-old ticket open?

ikegami commented 5 months ago

No. Without when, this issue is moot.

jkeenan commented 5 months ago

No. Without when, this issue is moot.

Okay. I'll self-assign for the purpose of closing it when we complete the removal of when. Thanks.

jkeenan commented 1 week ago

No. Without when, this issue is moot.

Okay. I'll self-assign for the purpose of closing it when we complete the removal of when. Thanks.

While given/when/smartmatch has been removed from blead, the decision has been controversial. So this ticket should remain open until the issue is definitively resolved.