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

I got my code to work, so the question is academic at this point, but I'm wondering why it worked the way it did....

I'm calling a sub in a module that returns an array ref, and I wanted three elements out of the array as a slice. So I did this:

$r = $dbh->r_sql(...); my @s = $r->[1..3];
Well, all that produced was a warning that Argument "" isn't numeric in aelem at ...

While using my tried-and-true debugging method of "change something, try it again", I actually looked up perlref and noted that -> is just for individual elements of array refs. So I tried this:

$r = $dbh->r_sql(...); my @s = @$r[1..3];
It worked fine, but it sure looks awful.

So, the question: Why can I get a single element from an array ref with ->, but not a slice? Is there a deeper reason or just parser capriciousness?

I'm using 5.005_02 on HP-UX, if it matters.

TIA

Replies are listed 'Best First'.
Re: Extracting a slice from an array ref
by dragonchild (Archbishop) on Aug 15, 2001 at 02:24 UTC
    *grins* It's actually quite simple. It has to do with what you're operating on. A dereference, using ->, is expecting an array-reference, which is a scalar. Hence, the $r. A slicing expects an array, which is a list. Hence, the @$r.

    Incidentally, if you wanted to take a slice of a hash-ref, as slicing demands an array, you would have to do the following: @list = @{$href}{qw(key1 key2 key3)};

    ------
    /me wants to be the brightest bulb in the chandelier!

    Vote paco for President!

Re: Extracting a slice from an array ref
by nietzel (Novice) on Aug 15, 2001 at 05:43 UTC
    Advanced PERL Programming by O'Reilly ( page 7 & 8 )

    This is the reference as to what you seek!

    To sum it up:

    my @s = $r->[1..3];

    Where [1..3] is treated as a comma seperated expression.

    The result of this expression is the last term in the array, in this case [3].

    Now we have $r->[3] which of course accesses a specific element from array $r.

    As you can now see this is not what you intended!

    Your actual (but unrelated) error Argument "" isn't numeric in aelem at ... is from using the range [1..3], where the range [1,2,3] will not produce this error (but a different one!).

    regards,
    Earle
      That is actually not the case.   my @s = $r->[1..3]; In this snippet, 1..3 is not treated as a comma separated expression, resulting in the value 3.

      In fact, 1..3 is in scalar context, and so it is the flip-flop operator. Since the left operand is just a constant, there is an implicit comparison to $., which returns false, resulting in the warning: Argument "" isn't numeric in aelem ... The interesting thing is that 1..3 in scalar context returns "" for false, rather than the special false value consisting of both "" and 0.

      Check out perlop for more on the wacky .. operator.

Re: Extracting a slice from an array ref
by Ven'Tatsu (Deacon) on Aug 15, 2001 at 10:24 UTC
    in ARRAYREF->[EXPR] EXPR is evaluated in scalar context. So .. is treated as the flip-flop style range operrator and not expanded into a list. Which when numeric literals are used they are compared to $.
(tye)Re: Extracting a slice from an array ref
by tye (Sage) on Aug 15, 2001 at 19:22 UTC

    See References Quick Reference. -> is basically short-hand for "${...}" which means you can't use it as shorthand for "@{...}" nor "%{...}".

    But there is some support for adding a new array slice syntax of ->@[...] (and similar constructs) to allow more syntactic flexibility for dealing with references.

            - tye (but my friends call me "Tye")