Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

@array[1] is valid??

by jdklueber (Beadle)
on Aug 04, 2003 at 18:49 UTC ( #280756=perlquestion: print w/replies, xml ) Need Help??
jdklueber has asked for the wisdom of the Perl Monks concerning the following question:

O Monks-
I thought I knew what I was doing. I thought that 7 years of coding Perl would've taught me most of the tricks... or, at least, brought me the insight to explain this little puzzle. A coworker brought this to my attention:

Given an array...

@foo = (1,2,3);

This statement

print "@foo[1]\n";



I thought that this would be invalid Perl, yet it works. Given that you declare @foo, it even works under strict (though warnings will generate a message like "Scalar value @foo[1] better written as $foo[1] at C:\WINDOWS\DESKTOP\FOO.PL line 6.").

Anyone have an explanation of this behavior?

Jason Klueber


Fixed square brackets - dvergin 2003-08-04

Replies are listed 'Best First'.
Re: @array[1] is valid??
by allolex (Curate) on Aug 04, 2003 at 19:01 UTC
    That's a slice you've got there. From the Camel Book:

    "Saying @foo[1] when you mean $foo[1]. The @foo[1] reference is an array slice, meaning an array consisting of the single element $foo[1]. Sometimes this doesn't make any difference, as in:

    print "the answer is @foo[1]\n";
    but it makes a big difference for things like:
    @foo[1] = <STDIN>;
    which will slurp up all the rest of STDIN, assign the first line to @foo[1], and discard everything else. This is probably not what you intended. Get into the habit of thinking that $ means a single value, while @ means a list of values, and you'll do okay."


Re: @array[1] is valid??
by halley (Prior) on Aug 04, 2003 at 18:56 UTC
    This is a one-element slice, which is better written as suggested. To explore slices, try:
    @foo = qw(zero one two three four five); print $_, $/ foreach (@foo[2..4]); print $/; print $_, $/ foreach (@foo[1,3,5]);

    [ e d @ h a l l e y . c c ]

Re: @array[1] is valid??
by dvergin (Monsignor) on Aug 04, 2003 at 19:02 UTC
    You are printing a single-element array slice. Perhaps this will make more clear what is happening.
    my @foo = (1,2,3); print "@foo[1,2]\n"; #prints: 2 3

    "Perl is a mess and that's good because the
    problem space is also a mess.
    " - Larry Wall

Re: @array[1] is valid??
by CountZero (Bishop) on Aug 04, 2003 at 19:04 UTC

    $foo[1] returns you a scalar and @foo[1] returns you a one element list.

    If you do it in a context which is sensible to being in scalar or list context, it might bite you, hence the message given by warnings.


    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: @array[1] is valid??
by Abigail-II (Bishop) on Aug 04, 2003 at 22:40 UTC
    As other have explained, it's a one element slice. Unfortunally, if you use it like this, Perl will issue a warning. I don't think it's right that Perl should give this warning; why should a one element slice trigger a warning when two, three, four, ..., or even a zero element slice don't? Furthermore, in most cases @foo 1 is used in rvalue context, where it won't matter anyway. The only place where it might go wrong, is where you use @foo 1 in lvalue context, and the RHS of the assignment returns different things in list and scalar context.

    But that's a rare case. In a more common case, which more often goes wrong is my ($foo) vs my $foo. But Perl doesn't warn there.

    And considering that in perl6, @foo 1 is the right way to address a single element (what's perl6 syntax for a one element slice?), I think that warning ought to removed from Perl.

    I've once send that in as a wish to p5p, but it was ignored.


      Is there any time when an explicit single element list (as opposed to one where the slice is determined dynamically) ever makes sense? I can't think of any. There are many occasions where my ($foo) makes sense, however. Assuming that warnings are meant to aid the user and do not have to be orthogonal, this warning makes sense IMHO.

      Makeshifts last the longest.

        #!/usr/bin/perl use strict; no warnings; my (@firstkey, @numberofkeys); my @list = qw /foo housekey blah carkey baz monkey/; @firstkey [0] = grep {/key$/} @list; $numberofkeys [0] = grep {/key$/} @list; print "@firstkey\n"; print "@numberofkeys\n"; __END__ housekey 3

        And yes, there are a million different ways to write this code, but that's not the point.

        But I can't think of a case where using @array [0] in non-lvalue context could return something else than $array [0].


Re: @array[1] is valid??
by jdklueber (Beadle) on Aug 05, 2003 at 13:53 UTC
    D'oh! I looked in my Camel book, but completely glossed over array slices... and since I've never once had to use them, I didn't realize that was the notation for it. Thanks everyone for filling in this blind spot for me!
    Jason Klueber


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://280756]
Approved by allolex
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2017-05-27 06:36 GMT
Find Nodes?
    Voting Booth?