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

Sorry to interrupt your tonsure creating dear monks but some advice please. It appears that Perl has adapted itself and has thrown our system's operation, established during a small routine change to our code.

The code creates several data types from definitions in a package, and stores them as a series of joined records - so one record holds the data pointer of another etc. (I have simplified the code to show you below) (It was so much easier to use address manipulations in 'C' but Perl's list manipulation was one of the original reasons why we went with Perl over 'C'). The trouble is that the code that was working before has now seemingly been banned as being anti- the Perl Spanish Inquisition's latest thinking on purity. Obviously a code rewrite/redesign is *not* desired at this stage so is there a better/newer/easier way of simply pushing the element onto the list held by the 'root' structure?

The error being given is:

Experimental push on scalar is now forbidden at C:\crap\adbtest.pl line 40, near "$rohan1;"

Experimental push on scalar is now forbidden at C:\Users\Alan\Documents\crap\adbtest.pl line 46, near "$rohan4;" Many thanks - ADB

Package/data sources package rohanType1; sub new { my $self = {}; # Discard the class name shift; $self->{'field11'} = undef; bless ($self); return $self; } return 1; package rohanType2; sub new { my $self = {}; shift; $self->{'field21'} = 0; bless ($self); return $self; } return 1; package rohanType3; sub new { my $self = {}; shift; # Pointer to rohanType1 $self->{'field31'} = undef; # Pointer to rohanType2 $self->{'field32'} = undef; bless ($self); return $self; } return 1; # Now the data structures used globally to store information used by t +he whole analysis, which holds # data types as defined above package rohanData; sub new { my $self = (); shift; $self->{'rohan1'} = undef; $self->{'rohan2'} = (); bless ($self); return $self; } return 1; ======================= Code my $rohanRoot; my $rohan1; my $rohan2; my $rohan3; my $rohan4; $rohanRoot = rohanData->new(); $rohan1 = rohanType1->new(); $rohan2 = rohanType2->new(); $rohan1->{'field11'} = $rohan2; $rohanRoot->{'rohan1'} = $rohan1; # my debug helper to see if add +resses are correct - not part of code push $rohanRoot->{'rohan2'}, $rohan1; # Interpreter/debugger objec +ts to this ... $rohan3 = rohanType1->new(); $rohan4 = rohanType2->new(); $rohan3->{'field11'} = $rohan4; push $rohanRoot->{'rohan2'}, $rohan3; # ... and this

Replies are listed 'Best First'.
Re: Experimental push on scalar now forbidden
by Corion (Patriarch) on May 21, 2017 at 08:53 UTC

    Change

    push $rohanRoot->{'rohan2'}, $rohan1;

    to

    push @{ $rohanRoot->{'rohan2'} }, $rohan1;

    Calling push with a reference as its first argument did not prove to be a good approach. You need to pass an array as the first argument to push.

    Also, consider having your critical systems not auto-update and try to test your programs on a single system before upgrading.

    Update: Also see tybalt89s answer above, which shows what the syntax was replaced by.

      Calling push with a reference as its first argument did not prove to be a good approach

      May I ask why?

        I did a bit of digging in the archives. I believe the original proposal for autoderef is this: perl #78656: Allow push/pop/keys/etc to act on references (this already contains a long discussion). The feature was introduced in v5.14 (documented as experimental, but standardized warnings for experimental features weren't added until later, Update: in v5.20).

        This P5P thread appears to be one of the discussions about the problems with the feature: Bug in auto-dereferencing in 5.14? My understanding is that there were lots of small problems with it, some philosophical but several practical, that added up to this being a contentious feature. Just to pick out two examples, again just based on my understanding from skimming the discussions: First, given that each, keys, and values can operate on both hashes and arrays (since v5.12), what does $x autovivify to in my $x; keys $x;? Second, what about blessed references that overload their dereferencing operations?

        Since part of the reasoning behind introducing autoderef was to make some expressions simpler (push @{$foo{bar}{quz}}, $x; became push $foo{bar}{quz}, $x;), i.e. getting rid of the need for circumfix @{} and %{} dereferencing, the Postfix Dereference Syntax that was first introduced in v5.20 took care of that particular point (push @{$foo{bar}{quz}}, $x; became push $foo{bar}{quz}->@*, $x;). It seems to me that the discussion then generally moved in the direction that the problematic autoderef could be removed in favor of postfix deref (e.g. perl #119437: autoderef, the implicit deref in push REF and others, the future of auto-deref), until that then happened in v5.24 together with postfix deref being taken out of experimental status as a replacement.

        (Update: See also perlexperiment.)

        There have to be discussions as to the reasoning (typically, an experiment (certain operations such as push, pop etc on a scalar is one such experiment that made it into 5.14) don't work out. The majority of the time, a failure is due to a possible interference with future design considerations. This particular experiment was removed from 5.23 (dev track for 5.24).

        In this case, I haven't found out the discussions regarding any debates on this particular topic, but per perlexperiment for 5.24.0, it's clear that this feature was dropped for the Postfix Dereference syntax. tybalt89 provided an example of that, here.

        Of course, you can and always have been able to use the "circumfix operator" to push to a reference... push @{ $href->{aref} }, ...; or just a straight-up deref push @$aref, ...;.

        update: I said above: "The majority of the time, a failure is due to a possible interference with future design considerations."

        That may have been inaccurate, as I don't have statistics on the matter. Perl devs are under the order of perlpolicy, where the number one rule is to do their best to honour backwards-compatibility. Some of the experiments get downthumbed or footshot because something comes up that breaks things that used to work, is considered a "feature", and still need to work. My use of "majority" was wrong, as I truly don't know. I do know that at least some get written off due to future considerations, but I also know that some die due to breaking past compat, even if they live for a while.

Re: Experimental push on scalar now forbidden
by tybalt89 (Monsignor) on May 21, 2017 at 08:52 UTC
    push $rohanRoot->{'rohan2'}->@*, $rohan1;

      Kudos for throwing in an example with the post-dereference syntax. Although I don't use it personally because I try to make all of my code at least 5.8 compliant, it's nice to see this newer feature out there. It's not that often I see it in use.

Re: Experimental push on scalar now forbidden
by gsd4me (Beadle) on May 22, 2017 at 18:12 UTC
    Thanks to Corion and tybalt89 for their answers - I was nearly there with the former's suggestion with my playing but the latter suggestion would never have crossed my mind as it ('normal' programming language-wise) looks like a completely foreign language - shades of using APL in my past!!! BTW when I said that it threw our system's operation, it wasn't as bad as that (we are testing changes on a non-live system) but it threw our development/testing environment because we couldn't even get it to start due to the non-interpretation of the new script with the Perl version being used. We do know what we are doing. Again many thanks for the assistance. ADB
      Sorry I came late, but if you care more about compatibility than speed you could override push et al with backwards compatible functions.

      See subs , perlsub#Overriding-Built-in-Functions and CORE .

      BTW: since I have no access to 5.24 it'll be nice to know what prototype 'CORE::push' returns.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

      PS:

      >  looks like a completely foreign language - shades of using APL in my past!!

      calling the new syntax APL-like is an euphemism.

      I wonder sometimes if P5P has a real long term vision.

        "BTW: since I have no access to 5.24 it'll be nice to know what prototype 'CORE::push' returns."
        $ perl -v | head -2 | tail -1 This is perl 5, version 24, subversion 0 (v5.24.0) built for darwin-th +read-multi-2level $ perl -le 'print prototype "CORE::push"' \@@

        — Ken