Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Reference is experimental

by Anonymous Monk
on Oct 20, 2016 at 14:16 UTC ( [id://1174367]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I keep getting the following error message: "shift on reference is experimental at beta_table_maker line 27. Not an ARRAY reference at beta_table_maker line 27, <FILEHANDLE> line 1". How can I solve this? Thanks in advance

my($counter) = 0; my(@AoA); while (@ARGV){ my($filename) = $ARGV[$counter]; open (FILEHANDLE, $filename); my(@tmp) = <FILEHANDLE>; shift $tmp[0]; push @AoA, [ @tmp ]; close FILEHANDLE; $counter++; } my ($aref) = ''; foreach $aref (@AoA){ print "\t [ @$aref ],\n"; }

Replies are listed 'Best First'.
Re: Reference is experimental
by Corion (Patriarch) on Oct 20, 2016 at 14:22 UTC
    my(@tmp) = <FILEHANDLE>; shift $tmp[0];

    What do you expect these two lines of code to do?

    Did you maybe want to write

    my(@tmp) = <FILEHANDLE>; shift @tmp; # remove headers
      Which could also be written as
      my (undef, @tmp) = <FILEHANDLE>;
Re: Reference is experimental
by davido (Cardinal) on Oct 20, 2016 at 15:35 UTC

    Certainly by now you've discovered it, but you have an additional bug:

    while (@ARGV){

    Since nothing is ever shifted off of @ARGV, the loop will continue almost forever. $counter will increment past the last element in @ARGV, so $filename will start being undef after a few iterations, but you aren't checking the return value of open to ever know that you're failing to open files. Meanwhile you'll keep pushing empty arrayrefs onto @AoA until the system bogs down under the burden of the memory leak.

    After fixing that consider also using the 3-arg version of open, and checking for open success.


    Dave

Re: Reference is experimental
by Eily (Monsignor) on Oct 20, 2016 at 14:45 UTC

    There's another way to ignore the first line: (undef, my @tmp) = <FILEHANDLE>; Here the first line will be sent to undef (so actually thrown away), and the rest will be sent to @tmp.

    Besides, the my in front of @tmp means it's a brand new array that was just created, so with a different address/reference. You can write:
    push @AoA, \@tmp;, because [ @tmp ] actually means "create new array, copy all the values of @tmp, and return a reference to that new array", while \@tmp; is just "take a reference to the newly created @tmp".

Re: Reference is experimental
by Anonymous Monk on Oct 20, 2016 at 14:27 UTC

    shift should normally be given an array, like shift @tmp;, that removes (and returns) the first element from @tmp. When you say shift $tmp[0];, shift thinks you're trying to give it an array reference (the first element of the array), so it tries to dereference $tmp[0], which doesn't work because it's not a reference and that's why you get the "Not an ARRAY reference" error. That's a feature that was added in Perl 5.14, but was experimental, which is why you get the "shift on reference is experimental" warning, and the feature was removed again in Perl 5.24. It was replaced by the Postfix Dereference Syntax.

      I don't believe that postfix-deref was a replacement for shifting an aref... it's just a different way to dereference references.

      The problem here is that $tmp[0] is a scalar, and back in the days where shifting refs was experimental, it assumed that anything not an array should be a reference to one.

      As you've said, that experiment ended, and in 5.24.0+, we now get something a little different and descriptive (albeit still with an experimental warning):

      perl -wMstrict -E 'my @a=(1); shift $a[0]' Experimental shift on scalar is now forbidden at -e line 1, at EOF Execution of -e aborted due to compilation errors.

        The experimental feature was abandoned for the operators that work on both hashes and arrays (keys, values and each) because the design couldn't work properly for all array-like and hash-like things.

        The same problem didn't exist for the operators that work solely on arrays (push, pop, shift, unshift and splice(?)), but the feature was also abandoned for them to avoid a lack of symmetry with keys, values and each. However, it's worth noting that it was mentioned that newly-created postderef lessened the need for these.

Re: Reference is experimental
by AnomalousMonk (Archbishop) on Oct 20, 2016 at 16:07 UTC

    Further to davido's ++post: A more Perlish way to write this kind of loop (and the subsequent print loop) might be (using several other suggestions from this thread):

    my @AoA; for my $filename (@ARGV){ open my $filehandle, '<', $filename or die "opening '$filename': $ +!"; my (undef, @tmp) = <$filehandle>; push @AoA, \@tmp; close $filehandle; } foreach my $aref (@AoA){ print "\t [ @$aref ],\n"; }
    The for-loop iterates over the @ARGV array and that's that; you don't have to worry about managing $counter or depleting @ARGV, and the $filename variable is entirely local to the scope of the for-loop (as is $aref in the following print loop), and thus cannot conflict with the same variable name in an enclosing scope (but see below!).

    Update:

    ... thus cannot conflict with the same variable name in an enclosing scope.
    This statement is a bit misleading. A lexical for-loop iteration variable is completely localized within the scope of the loop regardless of whether or not a new lexical is declared for this purpose:
    c:\@Work\Perl\monks>perl -wMstrict -le "my $x = 'eks'; print qq{before loop: $x}; ;; for my $x (1, 2, 3) { print qq{in loop: $x}; } ;; print qq{after loop: $x}; " before loop: eks in loop: 1 in loop: 2 in loop: 3 after loop: eks c:\@Work\Perl\monks>perl -wMstrict -le "my $x = 'eks'; print qq{before loop: $x}; ;; for $x (1, 2, 3) { print qq{in loop: $x}; } ;; print qq{after loop: $x}; " before loop: eks in loop: 1 in loop: 2 in loop: 3 after loop: eks
    Thus, the only "conflict" that can arise is due to confusion in the mind of the programmer. :)


    Give a man a fish:  <%-{-{-{-<

Re: Reference is experimental
by Phenomanan (Monk) on Oct 20, 2016 at 14:32 UTC

    The important line: "Not an ARRAY reference at beta_table_maker line 27"

    It's basically exactly what it says; you need to give it an array instead of $tmp[0]. Try, shift @tmp instead.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1174367]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2024-04-25 19:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found