Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

@array[1] is valid??

by jdklueber (Beadle)
on Aug 04, 2003 at 18:49 UTC ( [id://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";

Yields

2

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
ookami@insightbb.com

/(bb)|[^b]{2}/
--Shakespeare

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."

    --
    Allolex

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.

    CountZero

    "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.

    Abigail

      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].

        Abigail

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
    ookami@insightbb.com

    /(bb)|^b{2}/
    --Shakespeare

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (7)
As of 2024-04-19 10:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found