Perl / perl5

đŸȘ The Perl programming language
https://dev.perl.org/perl5/
Other
1.94k stars 554 forks source link

Tied hash - hash slice - bug? #7838

Closed p5pRT closed 12 years ago

p5pRT commented 19 years ago

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

Searchable as RT34470$

p5pRT commented 19 years ago

From perl@wizbit.be

This is a bug report for perl from perl@​wizbit.be\, generated with the help of perlbug 1.34 running under perl v5.8.3.


Hello\,

There is a difference in result between @​hash{qw/a b c/}++ and @​tied_hash{qx/a b c/} :

Example​:

Case-1​:

#!/usr/bin/perl -l $\,=qq( & );

package C; use Tie​::Hash; @​ISA=qw/Tie​::StdHash/; sub STORE { print @​_; }

package main; tie %x\, qq(C); @​x{qw/a b c/}++

Output​:   C=HASH(0x815dc78) & c & 1

This means that the store routine is only called once\, even though it should be called for each element when a hash-slice is used.

Doing the same thing on a 'normal' hash will create the 3 keys\, where the first 2 have a value of undef\, and the last one a value of 1

Case-2​:   @​x{qw/a b c/} = 1; # instead of @​x{qw/a b c/}++

The result of this line is that the three keys are created\, the first one having the value 1 and the last two having a value of undef (which is the same behavoir as with a 'normal' hash)

Is this a bug or not? or it the @​normal_hash{qx/a b c/}++ an 'accidental feature' which has not been copied to tie?

I believe it is a bug since this behaviour isn't documented in the perltie POD...

Can this be checked out?

Bram



Flags​:   category=core   severity=low


Site configuration information for perl v5.8.3​:

Configured by Debian Project at Sat Mar 27 17​:07​:14 EST 2004.

Summary of my perl5 (revision 5.0 version 8 subversion 3) configuration​:   Platform​:   osname=linux\, osvers=2.4.25-ti1211\, archname=i386-linux-thread-multi   uname='linux kosh 2.4.25-ti1211 #1 thu feb 19 18​:20​:12 est 2004 i686 gnulinux '   config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i386-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.3 -Dsitearch=/usr/local/lib/perl/5.8.3 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.3 -Dd_dosuid -des'   hint=recommended\, useposix=true\, d_sigaction=define   usethreads=define use5005threads=undef useithreads=define usemultiplicity=define   useperlio=define d_sfio=undef uselargefiles=define usesocks=undef   use64bitint=undef use64bitall=undef uselongdouble=undef   usemymalloc=n\, bincompat5005=undef   Compiler​:   cc='cc'\, ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'\,   optimize='-O3'\,   cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -I/usr/local/include'   ccversion=''\, gccversion='3.3.3 (Debian 20040314)'\, gccosandvers=''   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 =' -L/usr/local/lib'   libpth=/usr/local/lib /lib /usr/lib   libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt   perllibs=-ldl -lm -lpthread -lc -lcrypt   libc=/lib/libc-2.3.2.so\, so=so\, useshrplib=true\, libperl=libperl.so.5.8.3   gnulibc_version='2.3.2'   Dynamic Linking​:   dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags='-rdynamic'   cccdlflags='-fPIC'\, lddlflags='-shared -L/usr/local/lib'

Locally applied patches​:  


@​INC for perl v5.8.3​:   /etc/perl   /usr/local/lib/perl/5.8.3   /usr/local/share/perl/5.8.3   /usr/lib/perl5   /usr/share/perl5   /usr/lib/perl/5.8   /usr/share/perl/5.8   /usr/local/lib/site_perl   .


Environment for perl v5.8.3​:   HOME=/root   LANG (unset)   LANGUAGE (unset)   LD_LIBRARY_PATH (unset)   LOGDIR (unset)  
PATH=/sbin​:/usr/sbin​:/bin​:/usr/bin​:/usr/bin/X11​:/usr/local/sbin​:/usr/local/bin​:/usr/games   PERL_BADLANG (unset)   SHELL=/bin/bash

p5pRT commented 19 years ago

From @davidnicol

This means that the store routine is only called once\, even though it should be called for each element when a hash-slice is used.

Doing the same thing on a 'normal' hash will create the 3 keys\, where the first 2 have a value of undef\, and the last one a value of 1

There is only one store\, but there may be three fetches. The autovivification happens at fetch time.

post-increment appears to increment the last element of hash slices but not against arrays in general. Is this by design or laxity?

p5pRT commented 19 years ago

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

p5pRT commented 19 years ago

From @nwc10

On Thu\, Mar 17\, 2005 at 11​:08​:00AM -0000\, Bram wrote​:

Is this a bug or not? or it the @​normal_hash{qx/a b c/}++ an 'accidental feature' which has not been copied to tie?

On Tue\, Mar 29\, 2005 at 05​:30​:27PM -0600\, David Nicol wrote​:

post-increment appears to increment the last element of hash slices but not against arrays in general. Is this by design or laxity?

I assume that being able to increment a hash (or array) slice is a bug\, given that it's a syntax error on a plain array or hash​:

$ perl -le '++@​a; print foreach @​a' Can't modify array dereference in preincrement (++) at -e line 1\, near "@​a;" Execution of -e aborted due to compilation errors. $ perl -le '++@​a[0..1]; print foreach @​a'

1 $ perl -le '++%a; print foreach %a' Can't modify hash dereference in preincrement (++) at -e line 1\, near "%a;" Execution of -e aborted due to compilation errors. $ perl -le '++@​a{0..1}; print foreach %a' 1 1 0

$

So presumably that bug for the regular case needs fixing (to become a syntax error) rather than tie being brought into line with it.

Nicholas Clark

p5pRT commented 19 years ago

From perl5-porters@ton.iguana.be

In article \20050403195113\.GH96525@​plum\.\_lirble\.org\,   Nicholas Clark \nick@​ccl4\.org writes​:

On Thu\, Mar 17\, 2005 at 11​:08​:00AM -0000\, Bram wrote​:

Is this a bug or not? or it the @​normal_hash{qx/a b c/}++ an 'accidental feature' which has not been copied to tie?

On Tue\, Mar 29\, 2005 at 05​:30​:27PM -0600\, David Nicol wrote​:

post-increment appears to increment the last element of hash slices but not against arrays in general. Is this by design or laxity?

I assume that being able to increment a hash (or array) slice is a bug\, given that it's a syntax error on a plain array or hash​:

For golfers this is a well known fact :-)

As noted\, it works on array slices too​:

perl -wle '@​a=(1..4); @​a[1..2]++; print for @​a' 1 2 4 4

It's also sort of consistent. A slice is is documented to be a list of values\, and in fact the docs are quite explicit about @​a[1..2] being like ($a[1]\, $a[2])\, though the usage of "list" is quite ambiguous in that part of perldoc perldata. But that's *really* the way it behaves.

e.g.​:

perl -wle '@​a=1..4; print for \@​a[1..2]'

is not some array reference\, but​:

SCALAR(0x817350c) SCALAR(0x8173518)

just like you'd get from \($a[1]\, $a[2])

And in scalar context such a list of values evaluates to the last value​:

perl -wle '@​a=1..4; print for scalar @​a[0..2]' 3

So the result is actually as expected and I wouldn't call it a bug.

PS​: At least until you see that this doesn't work​:

perl -wle '@​a=1..4; ($a[1]\, $a[2])++' Useless use of array element in void context at -e line 1. Too many arguments for postincrement (++) at -e line 1\, near ")++" Execution of -e aborted due to compilation errors.

Maybe THAT'S a bug :-)

p5pRT commented 12 years ago

From @cpansprout

On Sun Apr 03 16​:22​:34 2005\, perl5-porters@​ton.iguana.be wrote​:

In article \20050403195113\.GH96525@​plum\.\_lirble\.org\, Nicholas Clark \nick@​ccl4\.org writes​:

On Thu\, Mar 17\, 2005 at 11​:08​:00AM -0000\, Bram wrote​:

Is this a bug or not? or it the @​normal_hash{qx/a b c/}++ an 'accidental feature' which has not been copied to tie?

On Tue\, Mar 29\, 2005 at 05​:30​:27PM -0600\, David Nicol wrote​:

post-increment appears to increment the last element of hash slices but not against arrays in general. Is this by design or laxity?

I assume that being able to increment a hash (or array) slice is a bug\, given that it's a syntax error on a plain array or hash​:

For golfers this is a well known fact :-)

As noted\, it works on array slices too​:

perl -wle '@​a=(1..4); @​a[1..2]++; print for @​a' 1 2 4 4

It's also sort of consistent. A slice is is documented to be a list of values\, and in fact the docs are quite explicit about @​a[1..2] being like ($a[1]\, $a[2])\, though the usage of "list" is quite ambiguous in that part of perldoc perldata. But that's *really* the way it behaves.

e.g.​:

perl -wle '@​a=1..4; print for \@​a[1..2]'

is not some array reference\, but​:

SCALAR(0x817350c) SCALAR(0x8173518)

just like you'd get from \($a[1]\, $a[2])

And in scalar context such a list of values evaluates to the last value​:

perl -wle '@​a=1..4; print for scalar @​a[0..2]' 3

So the result is actually as expected and I wouldn't call it a bug.

PS​: At least until you see that this doesn't work​:

perl -wle '@​a=1..4; ($a[1]\, $a[2])++' Useless use of array element in void context at -e line 1. Too many arguments for postincrement (++) at -e line 1\, near ")++" Execution of -e aborted due to compilation errors.

Maybe THAT'S a bug :-)

The ‘too many arguments’ thing is based on the number of operands at a syntactic level.

If an expression could (or usually would) return a list\, but is still one single term\, it gets evaluated in scalar context by operators that propagate scalar context.

A hash or array slice in scalar context evaluates to the last element of the slice.

$ perl -le' @​_ = a..z; print scalar @​_[0..5];' f

Hash and array slices are valid lvalues.

So I think this is not a bug\, and that the behaviour is as expected. Changing it would mean adding special cases.

--

Father Chrysostomos

p5pRT commented 12 years ago

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

p5pRT commented 12 years ago

From @ikegami

On Fri\, Dec 2\, 2011 at 1​:56 AM\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

A hash or array slice in scalar context evaluates to the last element of the slice.

$ perl -le' @​_ = a..z; print scalar @​_[0..5];' f

Hash and array slices are valid lvalues.

So I think this is not a bug\, and that the behaviour is as expected. Changing it would mean adding special cases.

I agree\, but I don't understand your explanation about perl -we'@​a=0..3; ($a[1]\, $a[2])++'?

The ‘too many arguments’ thing is based on the number of operands at a

syntactic level.

There is only one operand​: a list/comma op.

p5pRT commented 12 years ago

From @cpansprout

On Thu Dec 01 23​:20​:24 2011\, ikegami@​adaelis.com wrote​:

On Fri\, Dec 2\, 2011 at 1​:56 AM\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

A hash or array slice in scalar context evaluates to the last element of the slice.

$ perl -le' @​_ = a..z; print scalar @​_[0..5];' f

Hash and array slices are valid lvalues.

So I think this is not a bug\, and that the behaviour is as expected. Changing it would mean adding special cases.

I agree\, but I don't understand your explanation about perl -we'@​a=0..3; ($a[1]\, $a[2])++'?

The ‘too many arguments’ thing is based on the number of operands at a

syntactic level.

There is only one operand​: a list/comma op.

++ is processed by ck_fun\, which works that way. Yes\, it is inconsistent with other ops\, and I would like to fix it some day\, but that is not the subject of this ticket\, and #96006 already covers that.

--

Father Chrysostomos

p5pRT commented 12 years ago

From @ikegami

On Fri\, Dec 2\, 2011 at 11​:15 AM\, Father Chrysostomos via RT \< perlbug-followup@​perl.org> wrote​:

++ is processed by ck_fun\, which works that way. Yes\, it is inconsistent with other ops\, and I would like to fix it some day\, but that is not the subject of this ticket\, and #96006 already covers that.

Excellent. Thanks.