http://qs1969.pair.com?node_id=1218891

LanX has asked for the wisdom of the Perl Monks concerning the following question:

The following code is surprising me in two ways:

use strict; use warnings; use feature 'say'; use constant FL => 17,3,16; use constant FL2 => 22,4,13; my @row= "a".."z"; my @a = (" ") x 26; @a[17,3,16] = @row[22,4,13]; say "@a"; @a = (" ") x 26; @a[FL()] = @row[FL2]; say "@a";

It seems like constant folding isn't happening at all!!!

Am I missing something?

(This is perl 5, version 16,)

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Replies are listed 'Best First'.
Re: Constants lists in array slices
by kcott (Archbishop) on Jul 20, 2018 at 13:03 UTC

    G'day Rolf,

    Some info first:

    $ perl -v | head -2 | tail -1 This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-li +nux-thread-multi $ alias perle alias perle='perl -Mstrict -Mwarnings -Mautodie=:all -E'

    I first tried a cut-down version of your issue three different ways. All gave the correct slice; only the third had no warning message.

    $ perle 'use constant X => (1,3); my @y = "a".."z"; say for @y[X]' Scalar value @y[X] better written as $y[X] at -e line 1. b d $ perle 'use constant X => (1,3); my @y = "a".."z"; say for @y[+X]' Scalar value @y[+X] better written as $y[+X] at -e line 1. b d $ perle 'use constant X => (1,3); my @y = "a".."z"; say for @y[X()]' b d

    I then looked at these sections of constant: "List constants" and "CAVEATS".

    The first of those (see the WEEKDAYS example) suggested a fourth way to try; this gave the correct slice and no error:

    $ perle 'use constant X => 1,3; my @y = "a".."z"; say for @y[(X)]' b d

    The second has:

    "List constants are not inlined unless you are using Perl v5.20 or higher."

    This perhaps suggests why [X] (and probably [+X]) had problems; although I'm very much guessing here and don't really know what's going on under the hood.

    — Ken

      > The second has: "List constants are not inlined unless you are using Perl v5.20 or higher."

      ah thanks, that's the relevant part I missed. :)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Constants lists in array slices
by haukex (Archbishop) on Jul 20, 2018 at 13:04 UTC
    I get a warning for FL2 Scalar value @row[FL2] better written as $row[FL2] (ignoring that its a constant _list_)
    $ ./Porting/bisect.pl --target=miniperl --start=v5.16.3 --end=v5.26.0 +--expect-fail -e 'use warnings FATAL=>"all"; sub X () {2,3}; my @a=(" +a".."z"); print @a[X]' ... commit 429a25554a608b64c0ee46c1ffe19bab3718a3c8 Author: Father Chrysostomos <sprout@cpan.org> Date: Sat Sep 14 17:23:11 2013 -0700 Reduce false positives for @hsh{$s} and @ary[$s] warnings This resolves tickets #28380 and #114024. Commit 95a31aad5 did something similar to this for the new %hash{. +..} syntax. This commit extends it to @ slices and combines the two code paths. The heuristics in toke.c can easily produce false positives. So t +he op is flagged as being a candidate for the warning. Then when op. +c has the op tree available, it examines it to see whether the heuri +stic may have been a false positive. This avoids bugs with qw "foo bar baz" and sub calls triggering the warning. The source code is no longer available for the warning, so we reco +n- struct it from the op tree, skipping the subscript if it is anythi +ng other than a const op. This means that @hash{$foo} comes out as @hash{...} and @hash{foo} + as @hash{"foo"}. It also meeans that @hash{"]"} is displayed correct +ly instead of as @hash{"]. Commit 95a31aad5 also modified the heuristic for %hash{...} to exe +mpt qw altogether. But it did not exempt it if it was preceded by a t +ab. So this commit rectifies that. This commit also improves the false positive detection by exemptin +g any ops returning lists that can get past toke.c’s heuristic. I w +ent through the entire list of ops, but I may have missed some. Also, @ slices on the lhs of = are exempt, as they change the cont +ext and are hence actually useful. $ git tag --contains 429a25554a608b6 ... v5.20.0 ...
    Deparsing the code shows that FL and FL2 are called as functions @a[FL()] = @row[FL2()];
    $ ./Porting/bisect.pl --start=v5.16.3 --end=v5.26.0 -e '`$^X -Ilib -MO +=Deparse -e "use constant X=>3,4; \@x[X]"`=~/\@x\[3, 4\]/ and die' ... commit f815dc14d7c5540dfb5d02d001e0101c6266f281 Author: Father Chrysostomos <sprout@cpan.org> Date: Sun Jun 30 00:20:33 2013 -0700 Inline list constants These are inlined the same way as 1..5. We have two ops: rv2av | `-- const The const op returns an AV, which is stored in the op tree, and th +en rv2av flattens it. $ git tag --contains f815dc14d7c5540d ... v5.20.0 ... # *Update:* making sure it's not just the Deparse output that changed. +.. $ ./Porting/bisect.pl --start=v5.19.0 --end=v5.21.0 -e '`$^X -Ilib -MO +=Concise -e "use constant X=>3,4; \@x[X]"`=~/entersub/ or die' ... commit f815dc14d7c5540dfb5d02d001e0101c6266f281
      Thanks, bookmarked to learn more about bisect! :)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Constants lists in array slices
by hippo (Bishop) on Jul 20, 2018 at 12:31 UTC

    I'm not sure what you expect. Both output lines are the same:

    $ perl 1218891.pl Scalar value @row[FL2] better written as $row[FL2] at 1218891.pl line +17. e n w e n w $ perl -v | head This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-li +nux-thread-multi (with 25 registered patches, see perl -V for more detail) Copyright 1987-2012, Larry Wall Perl may be copied only under the terms of either the Artistic License + or the GNU General Public License, which may be found in the Perl 5 source ki +t. Complete documentation for Perl, including FAQ lists, should be found +on
      > I'm not sure what you expect.

      of course it's the same output.

      The performance depends on the generated opcodes.

      I wasn't aware that constant folding of lists wasn't implemented in "oldish" Perl versions.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        The performance depends on the generated opcodes.

        Thanks - this was the bit I missed from the OP. It is now clear to me why this was of a concern to you.

Re: Constants lists in array slices
by LanX (Saint) on Jul 20, 2018 at 12:25 UTC
    answering my own question:

    Testing with 5.24 shows constant folding of lists to work:

    X:\>perl -MO=Deparse -e"use constant L=>1,2,3; print @a[L]" use constant ('L', 1, 2, 3); print @a[1..3]; -e syntax OK

    seems like constant folding of lists was only added "some years" ago. ;-)

    update

    for comparison 5.18

    D:\>perl -MO=Deparse -e"use constant L=>1,2,3; print @a[L]" use constant ('L', 1, 2, 3); print @a[L()];

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice