Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__PACKAGE__ does not work as a hash key #13074

Closed
p5pRT opened this issue Jun 30, 2013 · 15 comments
Closed

__PACKAGE__ does not work as a hash key #13074

p5pRT opened this issue Jun 30, 2013 · 15 comments

Comments

@p5pRT
Copy link

p5pRT commented Jun 30, 2013

Migrated from rt.perl.org#118701 (status was 'rejected')

Searchable as RT118701$

@p5pRT
Copy link
Author

p5pRT commented Jun 30, 2013

From @jimav

This is a bug report for perl from james_avera@​yahoo.com,
generated with the help of perlbug 1.39 running under perl 5.14.2.


#!/usr/bin/perl
use strict; use warnings;

sub show($) { defined($_[0]) ? ("'".$_[0]."'") : "undef" }

my %table = ( main => "the-value" );

warn "__PACKAGE__ = ",show(__PACKAGE__),"\n";
warn "table{__PACKAGE__} = ", show($table{__PACKAGE__}), "\n";
warn "table{'main'} = ", show($table{'main'}), "\n";

die "bug" unless show($table{__PACKAGE__}) eq show($table{main});
# This dies



Flags​:
  category=core
  severity=low


Site configuration information for perl 5.14.2​:

Configured by Debian Project at Mon Apr 15 15​:34​:46 UTC 2013.

Summary of my perl5 (revision 5 version 14 subversion 2) configuration​:
 
  Platform​:
  osname=linux, osvers=3.2.0-37-generic, archname=x86_64-linux-gnu-thread-multi
  uname='linux lamiak 3.2.0-37-generic #58-ubuntu smp thu jan 24 15​:28​:10 utc 2013 x86_64 x86_64 x86_64 gnulinux '
  config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Dldflags= -Wl,-Bsymbolic-functions -Wl,-z,relro -Dlddlflags=-shared -Wl,-Bsymbolic-functions -Wl,-z,relro -Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.14 -Darchlib=/usr/lib/perl/5.14 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.14.2 -Dsitearch=/usr/local/lib/perl/5.14.2 -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.14.2 -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 -fstack-protector -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-O2 -g',
  cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fstack-protector -fno-strict-aliasing -pipe -I/usr/local/include'
  ccversion='', gccversion='4.7.3', 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.14.2
  gnulibc_version='2.17'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib -fstack-protector'

Locally applied patches​:
 


@​INC for perl 5.14.2​:
  /home/t/lib/perl
  /etc/perl
  /usr/local/lib/perl/5.14.2
  /usr/local/share/perl/5.14.2
  /usr/lib/perl5
  /usr/share/perl5
  /usr/lib/perl/5.14
  /usr/share/perl/5.14
  /usr/local/lib/site_perl
  .


Environment for perl 5.14.2​:
  HOME=/home/t
  LANG=en_US.UTF-8
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/home/t/bin​:/usr/lib/lightdm/lightdm​:/usr/local/sbin​:/usr/local/bin​:/usr/sbin​:/usr/bin​:/sbin​:/bin​:/usr/games​:/usr/local/games
  PERL5LIB=/home/t/lib/perl​:
  PERL_BADLANG (unset)
  SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jun 30, 2013

From @cpansprout

On Sat Jun 29 23​:53​:13 2013, jimav wrote​:

This is a bug report for perl from james_avera@​yahoo.com,
generated with the help of perlbug 1.39 running under perl 5.14.2.

-----------------------------------------------------------------
#!/usr/bin/perl
use strict; use warnings;

sub show($) { defined($_[0]) ? ("'".$_[0]."'") : "undef" }

my %table = ( main => "the-value" );

warn "__PACKAGE__ = ",show(__PACKAGE__),"\n";
warn "table{__PACKAGE__} = ", show($table{__PACKAGE__}), "\n";
warn "table{'main'} = ", show($table{'main'}), "\n";

die "bug" unless show($table{__PACKAGE__}) eq show($table{main});
# This dies

That’s because hash keys auto-quote. You have to write
$table{+__PACKAGE__}, $table{(__PACKAGE__)} or something similar.

The same applies, e.g., to $table{time}, which will use "time" rather
than "1372575833" as the hash key.

That’s a feature. :-)

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Jun 30, 2013

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

@p5pRT
Copy link
Author

p5pRT commented Jun 30, 2013

From @jkeenan

On 6/30/13 2​:53 AM, Jim Avera wrote​:

# New Ticket Created by Jim Avera
# Please include the string​: [perl #118701]
# in the subject line of all future correspondence about this issue.
#<URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=118701>

This is a bug report for perl from james_avera@​yahoo.com,
generated with the help of perlbug 1.39 running under perl 5.14.2.

-----------------------------------------------------------------
#!/usr/bin/perl
use strict; use warnings;

sub show($) { defined($_[0]) ? ("'".$_[0]."'") : "undef" }

my %table = ( main => "the-value" );

warn "__PACKAGE__ = ",show(__PACKAGE__),"\n";
warn "table{__PACKAGE__} = ", show($table{__PACKAGE__}), "\n";
warn "table{'main'} = ", show($table{'main'}), "\n";

die "bug" unless show($table{__PACKAGE__}) eq show($table{main});
# This dies

This limitation has been documented in 'perlmod' since 1997​:

#####
The special symbol C<__PACKAGE__> contains the current package, but
cannot (easily) be used to construct variable names.
#####

Is there any compelling reason why we should alter this long-standing
behavior?

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Jul 1, 2013

From @jimav

On 06/30/2013 05​:06 AM, James E Keenan via RT wrote​:

This limitation has been documented in 'perlmod' since 1997​:
##### The special symbol C<__PACKAGE__> contains the current package,
but cannot (easily) be used to construct variable names. ##### Is
there any compelling reason why we should alter this long-standing
behavior?

At this point in Perl's history not much is really compelling, so I
guess the answer is no.

But still, perldata says __PACKAGE__ etc. are "special literals" which
may (only) be used as "separate tokens". That makes it sound like they
are recognized while scanning regardless of the context.

I found this the hard way (i.e. as a silent bug) when $hash{__PACKAGE__}
interpreted __PACKAGE__ as a bareword or unquoted string, rather than as
a special literal token. It's another "hidden gotcha" which would be
nice to eliminate.

-Jim

@p5pRT
Copy link
Author

p5pRT commented Jul 2, 2013

From @mauke

On 02.07.2013 00​:42, Jim Avera wrote​:

On 06/30/2013 05​:06 AM, James E Keenan via RT wrote​:

This limitation has been documented in 'perlmod' since 1997​: ##### The
special symbol C<__PACKAGE__> contains the current package, but cannot
(easily) be used to construct variable names. ##### Is there any
compelling reason why we should alter this long-standing behavior?

Wrong part of the documentation. The above only means you can't say
$__PACKAGE__​::foo or similar. Jim isn't trying to construct a variable name.

At this point in Perl's history not much is really compelling, so I
guess the answer is no.

But still, perldata says __PACKAGE__ etc. are "special literals" which
may (only) be used as "separate tokens". That makes it sound like they
are recognized while scanning regardless of the context.

I found this the hard way (i.e. as a silent bug) when $hash{__PACKAGE__}
interpreted __PACKAGE__ as a bareword or unquoted string, rather than as
a special literal token. It's another "hidden gotcha" which would be
nice to eliminate.

As Father Chrysostomos explained, hash keys always autoquote
identifiers. Special-casing __PACKAGE__ would introduce another hidden
gotcha, not eliminate it.

--
Lukas Mai <plokinom@​gmail.com>

@p5pRT
Copy link
Author

p5pRT commented Jul 2, 2013

From @b2gills

On Mon, Jul 1, 2013 at 10​:46 PM, Lukas Mai <plokinom@​gmail.com> wrote​:

On 02.07.2013 00​:42, Jim Avera wrote​:

On 06/30/2013 05​:06 AM, James E Keenan via RT wrote​:

This limitation has been documented in 'perlmod' since 1997​: ##### The
special symbol C<__PACKAGE__> contains the current package, but cannot
(easily) be used to construct variable names. ##### Is there any
compelling reason why we should alter this long-standing behavior?

Wrong part of the documentation. The above only means you can't say
$__PACKAGE__​::foo or similar. Jim isn't trying to construct a variable name.

At this point in Perl's history not much is really compelling, so I
guess the answer is no.

But still, perldata says __PACKAGE__ etc. are "special literals" which
may (only) be used as "separate tokens". That makes it sound like they
are recognized while scanning regardless of the context.

I found this the hard way (i.e. as a silent bug) when $hash{__PACKAGE__}
interpreted __PACKAGE__ as a bareword or unquoted string, rather than as
a special literal token. It's another "hidden gotcha" which would be
nice to eliminate.

As Father Chrysostomos explained, hash keys always autoquote identifiers.
Special-casing __PACKAGE__ would introduce another hidden gotcha, not
eliminate it.

If you need the special literal there are a few easy ways to do it

  perl -E'%h=(main=>"Hello World"); say $h{+ __PACKAGE__ }'
  perl -E'%h=(main=>"Hello World"); say $h{ __PACKAGE__, }'
  perl -E'%h=(main=>"Hello World"); say $h{ ( __PACKAGE__ ) }'
  perl -E'%h=(main=>"Hello World"); say $h{ do{ __PACKAGE__ } }'

basically anything that tells perl (the compiler) that you want
it treated as a statement will work.

on 5.16 or later you can also pretend it is a subroutine
  perl -E'%h=(main=>"Hello World"); say $h{ __PACKAGE__() }'

@p5pRT
Copy link
Author

p5pRT commented Jul 2, 2013

From @jkeenan

On Mon Jul 01 22​:44​:37 2013, brad wrote​:

On Mon, Jul 1, 2013 at 10​:46 PM, Lukas Mai <plokinom@​gmail.com> wrote​:

On 02.07.2013 00​:42, Jim Avera wrote​:

On 06/30/2013 05​:06 AM, James E Keenan via RT wrote​:

This limitation has been documented in 'perlmod' since 1997​: #####
The
special symbol C<__PACKAGE__> contains the current package, but
cannot
(easily) be used to construct variable names. ##### Is there any
compelling reason why we should alter this long-standing behavior?

Wrong part of the documentation. The above only means you can't say
$__PACKAGE__​::foo or similar. Jim isn't trying to construct a
variable name.

At this point in Perl's history not much is really compelling, so I
guess the answer is no.

But still, perldata says __PACKAGE__ etc. are "special literals"
which
may (only) be used as "separate tokens". That makes it sound like
they
are recognized while scanning regardless of the context.

I found this the hard way (i.e. as a silent bug) when
$hash{__PACKAGE__}
interpreted __PACKAGE__ as a bareword or unquoted string, rather
than as
a special literal token. It's another "hidden gotcha" which would
be
nice to eliminate.

As Father Chrysostomos explained, hash keys always autoquote
identifiers.
Special-casing __PACKAGE__ would introduce another hidden gotcha,
not
eliminate it.

If you need the special literal there are a few easy ways to do it

perl \-E'%h=\(main=>"Hello World"\); say $h\{\+ \_\_PACKAGE\_\_ \}'
perl \-E'%h=\(main=>"Hello World"\); say $h\{ \_\_PACKAGE\_\_\, \}'
perl \-E'%h=\(main=>"Hello World"\); say $h\{ \( \_\_PACKAGE\_\_ \) \}'
perl \-E'%h=\(main=>"Hello World"\); say $h\{ do\{ \_\_PACKAGE\_\_ \} \}'

basically anything that tells perl (the compiler) that you want
it treated as a statement will work.

on 5.16 or later you can also pretend it is a subroutine
perl -E'%h=(main=>"Hello World"); say $h{ __PACKAGE__() }'

So, do we have a bug here?

A feature?

Something that needs better documentation?

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2013

From @b2gills

On Tue, Jul 2, 2013 at 5​:52 PM, James E Keenan via RT
<perlbug-followup@​perl.org> wrote​:

On Mon Jul 01 22​:44​:37 2013, brad wrote​:

On Mon, Jul 1, 2013 at 10​:46 PM, Lukas Mai <plokinom@​gmail.com> wrote​:

On 02.07.2013 00​:42, Jim Avera wrote​:

On 06/30/2013 05​:06 AM, James E Keenan via RT wrote​:

This limitation has been documented in 'perlmod' since 1997​: #####
The
special symbol C<__PACKAGE__> contains the current package, but
cannot
(easily) be used to construct variable names. ##### Is there any
compelling reason why we should alter this long-standing behavior?

Wrong part of the documentation. The above only means you can't say
$__PACKAGE__​::foo or similar. Jim isn't trying to construct a
variable name.

At this point in Perl's history not much is really compelling, so I
guess the answer is no.

But still, perldata says __PACKAGE__ etc. are "special literals"
which
may (only) be used as "separate tokens". That makes it sound like
they
are recognized while scanning regardless of the context.

I found this the hard way (i.e. as a silent bug) when
$hash{__PACKAGE__}
interpreted __PACKAGE__ as a bareword or unquoted string, rather
than as
a special literal token. It's another "hidden gotcha" which would
be
nice to eliminate.

As Father Chrysostomos explained, hash keys always autoquote
identifiers.
Special-casing __PACKAGE__ would introduce another hidden gotcha,
not
eliminate it.

If you need the special literal there are a few easy ways to do it

perl \-E'%h=\(main=>"Hello World"\); say $h\{\+ \_\_PACKAGE\_\_ \}'
perl \-E'%h=\(main=>"Hello World"\); say $h\{ \_\_PACKAGE\_\_\, \}'
perl \-E'%h=\(main=>"Hello World"\); say $h\{ \( \_\_PACKAGE\_\_ \) \}'
perl \-E'%h=\(main=>"Hello World"\); say $h\{ do\{ \_\_PACKAGE\_\_ \} \}'

basically anything that tells perl (the compiler) that you want
it treated as a statement will work.

on 5.16 or later you can also pretend it is a subroutine
perl -E'%h=(main=>"Hello World"); say $h{ __PACKAGE__() }'

So, do we have a bug here?

A feature?

Something that needs better documentation?

Thank you very much.
Jim Keenan

---
via perlbug​: queue​: perl5 status​: open
https://rt-archive.perl.org/perl5/Ticket/Display.html?id=118701

This is an intended feature, not a bug.


As for documentation, we always could use improvement

If we added a bit about how to use the special literal
__PACKAGE__ as a hash key,
we would need to add it to every
keyword / op / subroutine that is in Perl.

Maybe we could add it to perldata in the subscripts section.

I don't think it's worth holding this ticket open for that though.

---

There was a bit of discussion about allowing this to do
what beginners may think it does​:

  __PACKAGE__​::SubPackage

but that is not the topic of this bug report.

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2013

From @jimav

On 07/02/2013 03​:52 PM, James E Keenan via RT wrote​:

As Father Chrysostomos explained, hash keys always autoquote

identifiers.

Special-casing __PACKAGE__ would introduce another hidden gotcha,
not
eliminate it.

If you need the special literal there are a few easy ways to do it

 perl \-E'%h=\(main=>"Hello World"\); say $h\{\+ \_\_PACKAGE\_\_ \}'
 perl \-E'%h=\(main=>"Hello World"\); say $h\{ \_\_PACKAGE\_\_\, \}'
 perl \-E'%h=\(main=>"Hello World"\); say $h\{ \( \_\_PACKAGE\_\_ \) \}'
 perl \-E'%h=\(main=>"Hello World"\); say $h\{ do\{ \_\_PACKAGE\_\_ \} \}'

basically anything that tells perl (the compiler) that you want
it treated as a statement will work.

on 5.16 or later you can also pretend it is a subroutine
perl -E'%h=(main=>"Hello World"); say $h{ __PACKAGE__() }'

So, do we have a bug here?

A feature?

Something that needs better documentation?
Thank you very much.
Jim Keenan
IMO hidden or silent gotchas are the last significant
software-engineering risk specific to Perl, now that the fundamental
machinery works reliably (and btw, thanks immensely to all who made that
happen!)

The special __(PACKAGE|FILE|LINE)__ symbols are well-documented and
vanishingly unlikely to be innocently used as an application symbol. So
it's hard to see how special-casing them to always be treated as string
literals with the implied values (and never auto-quote themselves) would
make things worse. Removing hidden or silent traps is always a good
thing in the abstract.

But I'm not familiar with perl internals, so doing so might be
excessively risky.

I think those who would do the work are the only ones qualified to say
whether fixing this is prudent.

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2013

From @ikegami

On Tue, Jul 2, 2013 at 9​:09 PM, Jim Avera <james_avera@​yahoo.com> wrote​:

The special __(PACKAGE|FILE|LINE)__ symbols are well-documented and
vanishingly unlikely to be innocently used as an application symbol. So
it's hard to see how special-casing them to always be treated as string
literals with the implied values (and never auto-quote themselves) would
make things worse.

You could say exactly the same for `split`, `uc`, etc

And that's why it would make things worse.

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2013

From @rjbs

We're not changing this.

--
rjbs

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2013

From [Unknown Contact. See original ticket]

We're not changing this.

--
rjbs

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2013

@rjbs - Status changed from 'open' to 'rejected'

@p5pRT p5pRT closed this as completed Jul 3, 2013
@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2013

From @jimav

On 07/03/2013 04​:08 AM, Eric Brine wrote​:

On Tue, Jul 2, 2013 at 9​:09 PM, Jim Avera <james_avera@​yahoo.com
<mailto​:james_avera@​yahoo.com>> wrote​:

The special \_\_\(PACKAGE|FILE|LINE\)\_\_ symbols \.\.\. it's hard to see
how special\-casing them to always be treated as string literals
with the implied values \(and never auto\-quote themselves\) would
make things worse\. 

You could say exactly the same for `split`, `uc`, etc

Ok, I see your point. Death, taxes, and ambiguous programming languages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant