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

Hello Monks,

I have a function that got a reference to an array passed. I wanted to get the array using

sub my_func{ @vals = @{ shift }; ... }
The interpreter tells me this is ambiguous. Replacing @{ shift } with @{ shift() } works fine. Yet I cannot see the ambiguity of the first statement. Can anyone explain the other meaning to me?

Cheers,
PerlingTheUK

Replies are listed 'Best First'.
Re: Ambiguity of @{ shift }
by davido (Cardinal) on Sep 24, 2004 at 07:14 UTC

    It is ambiguous. You might mean shift(), or you might mean @shift. The construct @{ shift } could mean either thing. See, for example:

    use strict; use warnings; $, = "\t"; my @foo = qw/this that/; print @{ foo }, "\n"; my @shift = qw/those these/; print @{ shift }, "\n"; mysub( [qw/them theirs/] ); sub mysub { print @{ shift }, "\n"; print @{ shift() }, "\n"; }

    Dave

Re: Ambiguity of @{ shift }
by Corion (Patriarch) on Sep 24, 2004 at 07:09 UTC

    Compare

    my @shift; @{shift} = ( 0, 8, 8, 7.5, 8, 8.5, 0 ); my @weekday = qw(sun mon tue wed thu fri sat); for (0..$#shift) { printf "On %s I work %s hours", $weekday[$_], $shift[$_]; };

    against your function. @{STRING} is a way to access the array variable @STRING, at least as long as no strict 'refs' is in effect. For example the stupid idea to access a variable by its name could be implemented like that. The conflict arises because Perl and perl don't know whether you meant the string "shift" or the function shift, so it doesn't know what to do, and decides for one of the two but warns you of the other possibility.

Re: Ambiguity of @{ shift }
by TimToady (Parson) on Sep 24, 2004 at 23:01 UTC
    You may be pleased to know that this ambiguity goes away completely in Perl 6. The @{ expr } syntax is now entirely reserved for dereferencing hard references, and disambiguation of interpolations is handled in a cleaner way. See http://dev.perl.org/perl6/synopsis/S02.html for more.
Re: Ambiguity of @{ shift }
by Zaxo (Archbishop) on Sep 24, 2004 at 07:15 UTC

    The other syntax - the one perl is guessing wrong - is @{foo} being a form of the array @foo. Perl is not looking first for a builtin function there, but a bareword.

    You can use parens as you did, or place a harmless operator in front of the shift.

    my @shift = qw/a shifty array/; sub foo { print @{shift}; my @vars = @{+shift}; print @{vars} } foo [qw/A mere example/]; __END__
    which prints, ashiftyarrayAmereexample

    After Compline,
    Zaxo

Re: Ambiguity of @{ shift }
by Juerd (Abbot) on Sep 24, 2004 at 11:39 UTC

    A very idiomatic way of breaking ambiguity is to use the no-op unary +.

    my @foo = @{+shift}; print +(split)[2]; $hash{+lc}++; # etcetera

Re: Ambiguity of @{ shift }
by Anonymous Monk on Sep 24, 2004 at 07:13 UTC
    The interpreter warned you because you turned warnings on. Compare to
    perl -we'sub foo{66}; die @{ foo }'
    which warns Ambiguous use of @{foo} resolved to @foo at -e line 1.

    Compare once again to

    perl -we'die shift =>1' 1 perl -we'die shift() =>1' 1
Re: Ambiguity of @{ shift }
by ihb (Deacon) on Sep 24, 2004 at 12:44 UTC

    It might be worth noting that the ${foo} syntax is used in interpolation to separate variable name from following text when necessary. Thus,     print "bar$foo" . 'baz'; can be written     print "bar${foo}baz";

    ihb

    Read argumentation in its context!

Re: Ambiguity of @{ shift }
by PerlingTheUK (Hermit) on Sep 24, 2004 at 07:36 UTC
    Thank you all, that was a very helpful insight.

    Cheers,
    PerlingTheUK