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

Today I stumbled across a curious problem with my Perl code. I tried the following expression:
print shift sort @array;
which the interpreter rejected with the complaint
Type of arg 1 to shift must be array (not sort) at script.pl line 7, n +ear "@array;"
However, the following does work as desired:
my @a = ( 4, 1, 3, 2 ); my @b = sort @a; print shift @b;

So far, I was under the impression that
1. sort @a returns an array, namely the sorted version of @a. 2. shift takes an array as argument and returns a scalar.

Based on the interpreter's feedback I now realise my previous Perl world view must have been faulty in some respect.
Can anybody please enlighten me as to where the problem with the first code snippet above is?

Thanks and regards -

Pat

Replies are listed 'Best First'.
Re: Why does 'print shift sort @array' not work?
by kennethk (Abbot) on Feb 26, 2009 at 18:59 UTC

    The problem is that sort @a returns a list, not an array. What you've written is equivalent in syntax to shift (1,2,3). A read of perldata might provide some insight.

    Update: In addition to ikegami's solutions below, you can use an anonymous array to make your code work. Pointless use of a shift, though, unless you store the array ref.

    @array = ( 4, 1, 3, 2 ); print shift @{[sort @array]}; # Prints 1 print shift @{$sorted_ref = [sort @array]}; # Prints 1 and stores rema +ining values
Re: Why does 'print shift sort @array' not work?
by ikegami (Patriarch) on Feb 26, 2009 at 19:04 UTC
    shift requires an array. sort doesn't return an array. (An array can't be even be returned by subs or functions.)

    Solution:

    print( (sort @array)[0] );

    Or if you were assigning to a scalar,

    my ($first) = sort @array;

    Update: Why sort at all?

    use List::Util qw( minstr ); print( minstr @array );
Re: Why does 'print shift sort @array' not work?
by almut (Canon) on Feb 26, 2009 at 19:03 UTC

    As shift removes an element from its argument (an array), there must be an actual array data structure to remove from. In your case it's just a list of values on the Perl internal stack.

      Thanks to almut - and all the others who took the time to respond.

      I was erroneously under the impression that the terms 'list' and 'array' are fully synonymous in Perl ... which, of course, they are not. Most of the comments posted confirm, what I could have found at the beginning of chapter 3 in the Llama book as well where it says:
      "A list is an ordered collection of scalars. An array is a variable that contains a list. In Perl, the two terms are often used as if they're interchangeable. But, to be accurate, the list is the data, and the array is the variable."
      With shift operating on an array and returning a list, all is clear now. Thanks again to all of you who contributed to the clarification.

      Cheers -

      Pat
Re: Why does 'print shift sort @array' not work?
by hbm (Hermit) on Feb 26, 2009 at 19:18 UTC

    Another option is to put the results of sort into an anonymous array and then dereference:

    print shift @{[sort @array]}

      What's the value of shift @{[sort @array]} over (sort @array)[0]?

        I said "another", not "a more valuable." As for preferable, I think it depends. Consider:

        print pop @{[sort qw(a f e b)]}; print (reverse sort qw(a f e b))[0]; use List::Util qw(maxstr); print maxstr qw(a f e b);

        Other than that print (sort @array)[0] would be a syntax error without a + snuck in the right place? :)

        The cake is a lie.
        The cake is a lie.
        The cake is a lie.

        A reply falls below the community's threshold of quality. You may see it by logging in.