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

can't use ternary on lhs of push to return array lvalue #14436

Closed
p5pRT opened this issue Jan 21, 2015 · 17 comments
Closed

can't use ternary on lhs of push to return array lvalue #14436

p5pRT opened this issue Jan 21, 2015 · 17 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 21, 2015

Migrated from rt.perl.org#123648 (status was 'open')

Searchable as RT123648$

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2015

From @rjbs

Created by @rjbs

This works​:

  ~$ perl -le '($ARGV[0] ? @​a : @​b) = (1,2,3); print "A<@​a> B<@​b>"' 1
  A<1 2 3> B<>
  ~$ perl -le '($ARGV[0] ? @​a : @​b) = (1,2,3); print "A<@​a> B<@​b>"' 0
  A<> B<1 2 3>

Ternary as lvalue is well-established, and the source of my favorite warning​:

  ~$ perl -le '($ARGV[0] ? $a : @​b) = (1,2,3); print "A<@​a> B<@​b>"' 0
  Assignment to both a list and a scalar at -e line 1, near ");"

It used to be that you couldn't use a ternary as the first value to push for
any reason​:

  ~$ perl5.8.8 -e 'push(($x ? $y : $z), 1)'
  Type of arg 1 to push must be array (not null operation) at -e line 1, at end
  of line

It doesn't matter whether y/z are both arrays, either.

This changed in perl v5.14, with autoderef​:

  ~$ perl -le '$y = []; $z = []; push(($x ? $y : $z), 1); print "Y<@​$y> Z<@​$z>"'
  Y<> Z<1>

...but only for scalars. Kinda.

  ~$ perl -e 'push(($x ? @​y : @​z), 1)'
  Not an ARRAY reference at -e line 1.

Since the first argument is not a literal array, we use the "push EXPR, LIST"
form, which expects a scalar expression. Those arrays, in scalar context, are
numbers. You can't @​{} a number.

I don't think this is a bug... but! If autoderef ends up being removed the
semantics of the first argument become less nailed-down. Would there remain a
compelling reason for a ternary (and other expressions) to be rejected?

In the meantime, of course, there's this workaround​:

  ~$ perl -le 'use experimental "postderef";
  push(($x ? \@​y : \@​z)->@​*, 1); print "Y<@​y> Z<@​z>"'
  Y<> Z<1>

:-)

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.21.5:

Configured by rjbs at Mon Oct 20 13:54:04 EDT 2014.

Summary of my perl5 (revision 5 version 21 subversion 5) configuration:
   
  Platform:
    osname=darwin, osvers=14.0.0, archname=darwin-2level
    uname='darwin walrus.local 14.0.0 darwin kernel version 14.0.0: fri sep 19 00:26:44 pdt 2014; root:xnu-2782.1.97~2release_x86_64 x86_64 '
    config_args='-Dprefix=/Users/rjbs/.plenv/versions/21.5 -de -Dusedevel -A'eval:scriptdir=/Users/rjbs/.plenv/versions/21.5/bin''
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-common -DPERL_DARWIN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -I/opt/local/include',
    optimize='-O3',
    cppflags='-fno-common -DPERL_DARWIN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -I/opt/local/include'
    ccversion='', gccversion='4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.51)', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    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='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags =' -fstack-protector -L/usr/local/lib -L/opt/local/lib'
    libpth=/usr/local/lib /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0/lib /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib /usr/lib /opt/local/lib
    libs=-lgdbm -ldbm -ldl -lm -lutil -lc
    perllibs=-ldl -lm -lutil -lc
    libc=, so=dylib, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup -L/usr/local/lib -L/opt/local/lib -fstack-protector'



@INC for perl 5.21.5:
    /Users/rjbs/.plenv/versions/21.5/lib/perl5/site_perl/5.21.5/darwin-2level
    /Users/rjbs/.plenv/versions/21.5/lib/perl5/site_perl/5.21.5
    /Users/rjbs/.plenv/versions/21.5/lib/perl5/5.21.5/darwin-2level
    /Users/rjbs/.plenv/versions/21.5/lib/perl5/5.21.5
    .


Environment for perl 5.21.5:
    DYLD_LIBRARY_PATH (unset)
    HOME=/Users/rjbs
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/Users/rjbs/.plenv/versions/21.5/bin:/Users/rjbs/.plenv/libexec:/Users/rjbs/.plenv/plugins/perl-build/bin:/Users/rjbs/bin:/Users/rjbs/.rbenv/shims:/Users/rjbs/.rbenv/bin:/Users/rjbs/.plenv/shims:/Users/rjbs/.plenv/bin:/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/Users/rjbs/code/hla
    PERL_AUTOINSTALL=--skipdeps
    PERL_BADLANG (unset)
    PERL_MAILERS=sendmail:/Users/rjbs/bin/sendmail
    SHELL=/opt/local/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2015

From @rjbs

I forgot to mention that the use of a constant in the ternary will get the array in place before anything untoward can happen, confusing the situation a bit​:

  ~$ perl -le 'push((0 ? @​a : @​b), 1); print "A<@​a> B<@​b>"'
  A<> B<1>

--
rjbs

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2015

From @demerphq

You can always do this​: push @​{ $cond ? $x : $y }, $foo;

On 21 January 2015 at 17​:28, Ricardo SIGNES via RT
<perlbug-followup@​perl.org> wrote​:

I forgot to mention that the use of a constant in the ternary will get the array in place before anything untoward can happen, confusing the situation a bit​:

~$ perl -le 'push((0 ? @​a : @​b), 1); print "A<@​a> B<@​b>"'
A<> B<1>

--
rjbs

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

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2015

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

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2015

From @ikegami

On Wed, Jan 21, 2015 at 11​:24 AM, Ricardo SIGNES <perlbug-followup@​perl.org>
wrote​:

It used to be that you couldn't use a ternary as the first value to push
for
any reason​:

You could with a little extra​:

$ perl -E'push @​{ $x ? \@​y : \@​z }, 1; say "Y<@​y> Z<@​z>"'
Y<> Z<1>

Would there remain a compelling reason for a ternary (and other

expressions) to be rejected?

It's not being rejected.

$ perl -E'push $x ? \@​y : \@​z, 1; say "Y<@​y> Z<@​z>"'
push on reference is experimental at -e line 1.
Y<> Z<1>

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2015

From @rjbs

* Eric Brine <ikegami@​adaelis.com> [2015-01-21T13​:40​:02]

You could with a little extra​:

$ perl -E'push @​{ $x ? \@​y : \@​z }, 1; say "Y<@​y> Z<@​z>"'
Y<> Z<1>

Yes, and in fact I showed that already in my ticket, although I used postfix
rather than circumfix dereference.

Would there remain a compelling reason for a ternary (and other
expressions) to be rejected?

It's not being rejected.

$ perl -E'push $x ? \@​y : \@​z, 1; say "Y<@​y> Z<@​z>"'
push on reference is experimental at -e line 1.
Y<> Z<1>

I meant a ternary that results in an array rather than a reference, of course.

--
rjbs

@choroba
Copy link
Contributor

choroba commented Jun 19, 2020

With push on reference forbidden, this leads to an error now:

perl -wE 'push $x ? @a1 : @a2, @ARGV'
Experimental push on scalar is now forbidden at -e line 1, at EOF
Execution of -e aborted due to compilation errors.

@choroba
Copy link
Contributor

choroba commented Jun 19, 2020

This seems to contradict the documentation of the "Conditional Operator" which says

Scalar or list context propagates downward into the 2nd or 3rd argument,
whichever is selected.

@demerphq
Copy link
Collaborator

demerphq commented Jun 20, 2020 via email

@ikegami
Copy link
Contributor

ikegami commented Jun 20, 2020

This seems to contradict the documentation of the "Conditional Operator" which says

Scalar or list context propagates downward into the 2nd or 3rd argument,
whichever is selected.

Context only applies to valid code, and push syntactically expects an array, not an expression. This is documented as

push ARRAY, LIST

In more specific terms, that means

push @NAME, LIST
push @BLOCK, LIST
push EXPR->@*, LIST

(Also simplified forms of blocks like push @$a, ....)

@ikegami
Copy link
Contributor

ikegami commented Jun 20, 2020

Since the push EXPR, LIST experimental syntax has been rejected, this ticket is moot and should be closed.

@sobukus
Copy link

sobukus commented Jun 20, 2020

This is deeply confusing. If an expression returning an array is not valid as first argument for push, could we then at least make this consistent and improve the error? When you compare

$ perl -e 'push($a > 1 ? @x : @y, 3); print "@x | @y\n"'
Experimental push on scalar is now forbidden at -e line 1, near "3)"
Execution of -e aborted due to compilation errors.

and

$ perl -e 'push(0 > 1 ? @x : @y, 3); print "@x | @y\n"'
 | 3

Isn't it

a) a language bug that the compile-time constant expression passes the syntax check and does the expected pushing to one of the arrays, depending on condition, and
b) at very misleading error message, as I did never intend to push on a scalar. The expression clearly is supposed to return an array.

At the very least, the behaviour between compile-time constant expression and runtime-evaluated expression should be consistent.

@demerphq
Copy link
Collaborator

demerphq commented Jun 20, 2020 via email

@sobukus
Copy link

sobukus commented Jun 22, 2020

Should I open a new issue about this, nevertheless, or should this one here be reopened?

@demerphq
Copy link
Collaborator

demerphq commented Jun 22, 2020 via email

@khwilliamson
Copy link
Contributor

khwilliamson commented Jun 22, 2020 via email

@sobukus
Copy link

sobukus commented Jun 23, 2020

Well, there's #17883 now …

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

7 participants