Perl / perl5

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

%foo->@{...} works #17722

Open ikegami opened 4 years ago

ikegami commented 4 years ago

This is a bug report generated with the help of perlbug 1.41 running under perl 5.30.2.


The left side of -> is supposed to be an expression that returns a reference.

$ perl -we'my %foo; %foo->{a} = 1; print "ok\n";'
Can't use a hash as a reference at -e line 1.

But %foo->@{...} works.

$ perl -we'my %foo; %foo->@{"a"} = 1; print "ok\n";'
ok

Note that %foo->{a} used to work, but it was deemed to be a bug. It was deprecated in 5.12, and fixed in 5.22. The same should be done to %foo->@{...}. I haven't tested any of the other postfix dereference syntaxes to see if they have the same problem.

- ikegami


---
Flags:
    category=core
    severity=low
---
Site configuration information for perl 5.30.2:

Configured by ikegami at Sun Mar 15 17:27:10 EDT 2020.

Summary of my perl5 (revision 5 version 30 subversion 2) configuration:

  Platform:
    osname=linux
    osvers=4.4.0-18362-microsoft
    archname=x86_64-linux-thread-multi
    uname='linux tribble 4.4.0-18362-microsoft #476-microsoft fri nov 01 16:53:00 pst 2019 x86_64 x86_64 x86_64 gnulinux '
    config_args='-de -Dprefix=/home/ikegami/usr/perlbrew/perls/5.30.2t -DPERL_SUB_DEPTH_WARN=1000 -Dusethreads -Aeval:scriptdir=/home/ikegami/usr/perlbrew/perls/5.30.2t/bin'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='cc'
    ccflags ='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
    optimize='-O2'
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion=''
    gccversion='7.5.0'
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=3
    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-strong -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/7/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
    libs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.27.so
    so=so
    useshrplib=false
    libperl=libperl.a
    gnulibc_version='2.27'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='-Wl,-E'
    cccdlflags='-fPIC'
    lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'

Locally applied patches:
    Devel::PatchPerl 1.90

---
@INC for perl 5.30.2:
    /home/ikegami/usr/perlbrew/perls/5.30.2t/lib/site_perl/5.30.2/x86_64-linux-thread-multi
    /home/ikegami/usr/perlbrew/perls/5.30.2t/lib/site_perl/5.30.2
    /home/ikegami/usr/perlbrew/perls/5.30.2t/lib/5.30.2/x86_64-linux-thread-multi
    /home/ikegami/usr/perlbrew/perls/5.30.2t/lib/5.30.2

---
Environment for perl 5.30.2:
    HOME=/home/ikegami
    LANG=C.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/ikegami/usr/perlbrew/bin:/home/ikegami/usr/perlbrew/perls/latest/bin:.:/home/ikegami/bin:/home/ikegami/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/mnt/c/Program Files/WindowsApps/CanonicalGroupLimited.Ubuntu18.04onWindows_2020.1804.7.0_x64__79rhkp1fndgsc:/mnt/c/progs/sp5302-x64/c/bin:/mnt/c/progs/sp5302-x64/perl/site/bin:/mnt/c/progs/sp5302-x64/perl/bin:/mnt/c/Program Files/Intel/iCLS Client/:/mnt/c/Windows/system32:/mnt/c/Windows:/mnt/c/Windows/System32/Wbem:/mnt/c/Windows/System32/WindowsPowerShell/v1.0/:/mnt/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common:/mnt/c/WINDOWS/system32:/mnt/c/WINDOWS:/mnt/c/WINDOWS/System32/Wbem:/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/:/mnt/c/WINDOWS/System32/OpenSSH/:/mnt/c/Program Files/IDM Computer Solutions/UltraEdit:/mnt/c/Program Files/PuTTY/:/mnt/c/Program
Files/NVIDIA Corporation/NVIDIA NvDLISR:/mnt/c/Program Files (x86)/Intel/Intel(R) Management Engine Components/DAL:/mnt/c/Program Files/Intel/Intel(R) Management Engine Components/DAL:/mnt/c/Users/ikegami/AppData/Roaming/ActiveState/bin:/snap/bin
    PERLBREW_HOME=/home/ikegami/.perlbrew
    PERLBREW_MANPATH=/home/ikegami/usr/perlbrew/perls/latest/man
    PERLBREW_PATH=/home/ikegami/usr/perlbrew/bin:/home/ikegami/usr/perlbrew/perls/latest/bin
    PERLBREW_PERL=latest
    PERLBREW_ROOT=/home/ikegami/usr/perlbrew
    PERLBREW_SHELLRC_VERSION=0.88
    PERLBREW_VERSION=0.88
    PERL_BADLANG (unset)
    SHELL=/bin/bash
ikegami commented 4 years ago

Note that perlop doesn't explicitly mention ->@{...}, only that "the dereferencing cases (as opposed to method-calling cases) are somewhat extended by the postderef feature." The postderef feature is a no-op in 5.24+, so this part of the docs could clearly use some work.

Grinnz commented 4 years ago

That sentence is more referring to the postderef feature in the abstract, rather than the specific feature.pm argument. Perhaps it could be reworded to "postfix dereference syntax" like the referenced perlref section.

karenetheridge commented 4 years ago

backref: https://stackoverflow.com/questions/61237808/is-postderef-syntax-on-hashes-supported

backbackref: conversation on irc.freenode.org#perl 2020-04-15T2:02:00 UTC-0700

ikegami commented 4 years ago

Or conversely, re-allow %foo->{key}. Some might prefer doing %foo->@{...} over @foo{...}. It's the inconsistency that's the problem.

Grinnz commented 4 years ago

Allowing %foo->{key} would not make any sense, I can't fathom it was anything other than a bug to begin with. That is a dereference operation and a hash is not a reference, at best you could expect it to use the number of keys in the hash as a symbolic ref (not to mention that it's never worked on arrays).

ikegami commented 4 years ago

You are gravely mistaken about what people expect :) Personally, I prefer limiting it to references, but it would not be contrary to expectations for it to work on %foo, and it would be in the spirit of least surprise in some ways (and thus TIMTOWTDI).

Grinnz commented 4 years ago

The expectations of people that misunderstand Perl's syntax are not a good target for syntax extensions.

ikegami commented 4 years ago

We're talking about what the syntax should be, so people's expectations are relevant. Furthermore, we're talking about syntax that's been valid for 20 years, so it's kinda disingenuous to say they are mistaken in their understanding. Finally, I didn't say people might expect %foo->@{...}; I said people might prefer %foo->@{...}, meaning it might be something worth providing.

Grinnz commented 4 years ago

While indeed efforts are made toward bugwards compatibility, it is still just that, and I know of no significant usage of this syntax that would warrant more than the deprecation and removal it had. Regarding its worth, it is certainly not worth providing a new syntax inconsistent with the rest of Perl that would create expectations of other random syntaxes by extension.

ikegami commented 4 years ago

| a new syntax inconsistent with the rest of Perl

Except it's not. There's a 20 year history of non-references being accepted on the LHS of ->. Then there's keys(%h), push(@a, ...), etc. Hardly inconsistent! That's why I suggested it might be worth formalizing the concept.

EvanCarroll commented 4 years ago

I don't much care about this, but I found it intuitive as-is. I'm ok with the modification in behavior. To clarify the confusion: from my read of postderef it's mainly some kind of acknowledgement that sigils are a failure/losing battle and we should try something else. It seems of limited use to provide,

my %foo = ( foo => 1, bar => 2 );
my $bar = \%foo;
$bar->@{qw(foo bar)};

As a stylistically better (though longer) alternative to

@$bar{qw(foo bar)};

But to have a discontinuity between a slice from a ref, and a slice from a hash like,

$bar->@{qw(foo bar)};
@foo{qw(foo bar)};

Perhaps I was wrong, but it seems like the advantage of postderef was that sigils on use didn't have to change from the sigils on declaration. It seems like that read was wrong though and these serve a different function.