Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Perl: porters

[perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap?

 

 

Perl porters RSS feed   Index | Next | Previous | View Threaded


perlbug-followup at perl

May 2, 2012, 12:39 PM

Post #1 of 5 (99 views)
Permalink
[perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap?

# 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 [at] yahoo,
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


h.m.brand at xs4all

May 3, 2012, 2:10 AM

Post #2 of 5 (101 views)
Permalink
Re: [perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap? [In reply to]

On Wed, 02 May 2012 12:39:45 -0700, Jim Avera (via RT)
<perlbug-followup [at] perl> 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?

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 }
}

> 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

> 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/


nick at ccl4

May 3, 2012, 2:29 AM

Post #3 of 5 (96 views)
Permalink
Re: [perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap? [In reply to]

On Thu, May 03, 2012 at 11:10:43AM +0200, H.Merijn Brand wrote:
> On Wed, 02 May 2012 12:39:45 -0700, Jim Avera (via RT)
> <perlbug-followup [at] perl> 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 :-)

> > 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 {

> > 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


abigail at abigail

May 3, 2012, 3:09 AM

Post #4 of 5 (95 views)
Permalink
Re: [perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap? [In reply to]

On Wed, May 02, 2012 at 12:39:45PM -0700, Jim Avera wrote:
> # 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 [at] yahoo,
> 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


ikegami at adaelis

May 3, 2012, 9:32 AM

Post #5 of 5 (91 views)
Permalink
Re: [perl #112732] Subs ending in { @a } return list, not hashref; can Perl defend against this trap? [In reply to]

On Thu, May 3, 2012 at 5:10 AM, H.Merijn Brand <h.m.brand [at] xs4all> wrote:

>
> > 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).

Perl porters RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.