Skip Menu |
Report information
Id: 112732
Status: resolved
Priority: 0/
Queue: perl5

Owner: Nobody
Requestors: jimav <james_avera [at] yahoo.com>
Cc:
AdminCc:

Operating System: Linux
PatchStatus: (no value)
Severity: low
Type: library
Perl Version: 5.12.4
Fixed In: (no value)



Subject: Subs ending in { @a } return list, not hashref; can Perl defend against this trap?
Date: Wed, 02 May 2012 12:39:26 -0700
To: perlbug [...] perl.org
From: Jim Avera <james_avera [...] yahoo.com>
Download (untitled) / with headers
text/plain 4.4k
This is a bug report for perl from james_avera@yahoo.com, generated with the help of perlbug 1.39 running under perl 5.12.4. ----------------------------------------------------------------- In the following, Perl silently parses the {...} in the last line of each sub as a BLOCK rather than an anonymous-hash constructor. The functions return the list (a,1,b,1), not a hahsref as the programmer obviously intended: use struct; use warnings; sub f { my @keys = ("a","b"); { map{$_ => 1} @keys } } sub g { my @a = (a => 1, b => 2); { @a } } This is a trap. Can Perl do something to save programmers from it? One solution might be to actually recognize when {...} is the last thing in a sub definition and parse it as an expression in that case. Another might be to warn about *statements* consisting only of expressions with no side-effects, which would let the user know that a dangling "{ map{$_=>1} @keys }" was not handled by Perl as they expected. ----------------------------------------------------------------- --- Flags: category=library severity=low module=warnings --- Site configuration information for perl 5.12.4: Configured by Debian Project at Tue Sep 6 08:08:24 UTC 2011. Summary of my perl5 (revision 5 version 12 subversion 4) configuration: Platform: osname=linux, osvers=2.6.24-28-server, archname=x86_64-linux-gnu-thread-multi uname='linux allspice 2.6.24-28-server #1 smp wed aug 18 21:17:51 utc 2010 x86_64 x86_64 x86_64 gnulinux ' config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.12 -Darchlib=/usr/lib/perl/5.12 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.12.4 -Dsitearch=/usr/local/lib/perl/5.12.4 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Duse64bitint -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -Ui_libutil -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.12.4 -des' 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 -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2 -g', cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include' ccversion='', gccversion='4.6.1', 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 =' -fstack-protector -L/usr/local/lib' libpth=/usr/local/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib /usr/lib libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt perllibs=-ldl -lm -lpthread -lc -lcrypt libc=, so=so, useshrplib=true, libperl=libperl.so.5.12.4 gnulibc_version='2.13' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib -fstack-protector' Locally applied patches: --- @INC for perl 5.12.4: /home/jima/local/share/perl/5.12.4 /home/jima/local/share/perl /etc/perl /usr/local/lib/perl/5.12.4 /usr/local/share/perl/5.12.4 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.12 /usr/share/perl/5.12 /usr/local/lib/site_perl . --- Environment for perl 5.12.4: HOME=/home/jima LANG=en_US.UTF-8 LANGUAGE (unset) LD_LIBRARY_PATH=/home/jima/local/lib LOGDIR (unset) PATH=/home/jima/bin:/home/jima/local/bin:/home/jima/jima_tools/linux86_64/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/bin/X11:/usr/local/bin:/opt/openoffice.org3/program:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/games:. PERL5LIB=/home/jima/local/share/perl PERL_BADLANG (unset) SHELL=/bin/bash
Subject: Re: [perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap?
Date: Thu, 3 May 2012 11:10:43 +0200
To: perl5-porters [...] perl.org
From: "H.Merijn Brand" <h.m.brand [...] xs4all.nl>
Download (untitled) / with headers
text/plain 1.7k
On Wed, 02 May 2012 12:39:45 -0700, Jim Avera (via RT) <perlbug-followup@perl.org> wrote: Show quoted text
> In the following, Perl silently parses the {...} in the last line > of each sub as a BLOCK rather than an anonymous-hash constructor. > The functions return the list (a,1,b,1), not a hahsref > as the programmer obviously intended: > > use struct; use warnings; > sub f { > my @keys = ("a","b"); > { map{$_ => 1} @keys } > } > sub g { my @a = (a => 1, b => 2); { @a } } > > This is a trap. Can Perl do something to save programmers from it?
Yes, either put a + in front of the opening brace or add an explicit return: sub f { my @keys = ("a", "b"); +{ map { $_ => 1 } @keys } } sub g { my @a = (a => 1, b => 2); return { @a } } Show quoted text
> One solution might be to actually recognize when {...} is the last thing > in a sub definition and parse it as an expression in that case.
This issue comes back every now and then, and whatever way the current parsing is modified will break someone elses expectations. The ability to unambiguate using a + is easy enough to warrant not to change this Show quoted text
> Another might be to warn about *statements* consisting only of > expressions with no side-effects, which would let the user know that a > dangling "{ map{$_=>1} @keys }" was not handled by Perl as they expected.
No. Many people use this to explicitely create a scope, possibly with lexical variable, to avoid side effects or force auto-destruction. -- H.Merijn Brand http://tux.nl Perl Monger http://amsterdam.pm.org/ using perl5.00307 .. 5.14 porting perl5 on HP-UX, AIX, and openSUSE http://mirrors.develooper.com/hpux/ http://www.test-smoke.org/ http://qa.perl.org http://www.goldmark.org/jeff/stupid-disclaimers/
Subject: Re: [perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap?
Date: Thu, 3 May 2012 10:29:43 +0100
To: perl5-porters [...] perl.org
From: Nicholas Clark <nick [...] ccl4.org>
Download (untitled) / with headers
text/plain 2.1k
On Thu, May 03, 2012 at 11:10:43AM +0200, H.Merijn Brand wrote: Show quoted text
> On Wed, 02 May 2012 12:39:45 -0700, Jim Avera (via RT) > <perlbug-followup@perl.org> wrote: >
> > In the following, Perl silently parses the {...} in the last line > > of each sub as a BLOCK rather than an anonymous-hash constructor. > > The functions return the list (a,1,b,1), not a hahsref > > as the programmer obviously intended: > > > > use struct; use warnings; > > sub f { > > my @keys = ("a","b"); > > { map{$_ => 1} @keys } > > } > > sub g { my @a = (a => 1, b => 2); { @a } } > > > > This is a trap. Can Perl do something to save programmers from it?
We could make return statements mandatory :-) Show quoted text
> > One solution might be to actually recognize when {...} is the last thing > > in a sub definition and parse it as an expression in that case.
> > This issue comes back every now and then, and whatever way the current > parsing is modified will break someone elses expectations. The ability > to unambiguate using a + is easy enough to warrant not to change this
Worse than that, I think it's not possible. Too much lookahead would be needed, because the parser has to decide early whether the { is a block or a hash constructor. It's not able to defer that decision until it reaches the } And, unfortunately, in the example given, the code within the {} is valid for either interpretation of the { Show quoted text
> > Another might be to warn about *statements* consisting only of > > expressions with no side-effects, which would let the user know that a > > dangling "{ map{$_=>1} @keys }" was not handled by Perl as they expected.
> > No. Many people use this to explicitely create a scope, possibly with > lexical variable, to avoid side effects or force auto-destruction.
I think the key part of the request was that all code *within* the block had to have no side effects. The use case that you (Merijn) describe would (I think) always have some statement with side effects. However, I'm not sure how easy it is to "know" unambiguously whether a section of the optree has side effects. (I'm going to discount the hidden side effects of things lile the values read being tied or overloaded) Nicholas Clark
Subject: Re: [perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap?
Date: Thu, 3 May 2012 12:09:49 +0200
To: perl5-porters [...] perl.org
From: Abigail <abigail [...] abigail.be>
Download (untitled) / with headers
text/plain 1.4k
On Wed, May 02, 2012 at 12:39:45PM -0700, Jim Avera wrote: Show quoted text
> # New Ticket Created by Jim Avera > # Please include the string: [perl #112732] > # in the subject line of all future correspondence about this issue. > # <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=112732 > > > > This is a bug report for perl from james_avera@yahoo.com, > generated with the help of perlbug 1.39 running under perl 5.12.4. > > ----------------------------------------------------------------- > In the following, Perl silently parses the {...} in the last line > of each sub as a BLOCK rather than an anonymous-hash constructor. > The functions return the list (a,1,b,1), not a hahsref > as the programmer obviously intended: > > use struct; use warnings; > sub f { > my @keys = ("a","b"); > { map{$_ => 1} @keys } > } > sub g { my @a = (a => 1, b => 2); { @a } } > > This is a trap. Can Perl do something to save programmers from it? > > One solution might be to actually recognize when {...} is the last thing > in a sub definition and parse it as an expression in that case. > > Another might be to warn about *statements* consisting only of > expressions with no side-effects, which would let the user know that a > dangling "{ map{$_=>1} @keys }" was not handled by Perl as they expected.
Subs of the form: sub foo { ... 1; } or sub bar { ... $var; } are as common as dirt; I don't think people appreciate it if this starts warning. Abigail
CC: perl5-porters [...] perl.org
Subject: Re: [perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap?
Date: Thu, 3 May 2012 12:32:13 -0400
To: "H.Merijn Brand" <h.m.brand [...] xs4all.nl>
From: Eric Brine <ikegami [...] adaelis.com>
Download (untitled) / with headers
text/plain 840b
On Thu, May 3, 2012 at 5:10 AM, H.Merijn Brand <h.m.brand@xs4all.nl> wrote:
Show quoted text

> One solution might be to actually recognize when {...} is the last thing
> in a sub definition and parse it as an expression in that case.

This issue comes back every now and then, and whatever way the current
parsing is modified will break someone elses expectations. The ability
to unambiguate using a + is easy enough to warrant not to change this


I often have code of the form

sub {
   {
      ...
   }
   {
      ...
   }
   {
      ...
   }
}

If that last block becomes a hash, I'd likely get spurious warnings ("Useless use of anonymous hash ({}) in void context", "Odd number of elements in anonymous hash", "Unitialized value in hash"), and "next" and such would not work properly (although they're very unlikely to be used there).

Subject: Re: [perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap?
From: Zefram <zefram [...] fysh.org>
To: perl5-porters [...] perl.org
Date: Tue, 12 Dec 2017 02:58:41 +0000
Download (untitled) / with headers
text/plain 245b
The documentation of the hash/block disambiguation method was recently made more prominent in commit 557714184de18964b954b2c00fa13127fd3f216a for [perl #130958]. That's really all we can do in this area. This ticket should be closed. -zefram


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