Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the first item from a function that returns an array in Perl?

Tags:

perl

I have a function that returns an array, and I'd like to get just the first item from that array without ever declaring a variable for the array. Basically, it should be something like:

functionReturningArray()[1]

Except that doesn't work.

I really don't want to waste space declaring the whole array since I don't need it, and I'd rather not waste an extra line of code. Anyway to do this in one line?

like image 208
Eli Avatar asked Sep 16 '10 15:09

Eli


People also ask

How do I get the first element of an array in Perl?

The array variable name begins with the @ symbol. To refer to a single element of an array, the variable name must start with a $ followed by the index of the element in square brackets ( [] ). The index of the first array element is 0.

How do I find the first element of an array?

There are several methods to get the first element of an array in PHP. Some of the methods are using foreach loop, reset function, array_slice function, array_values, array_reverse, and many more. We will discuss the different ways to access the first element of an array sequentially.

How do I return an array in Perl?

return @list; # Returns array @list } my @results = findLines(); # or sub findLines { ... return \@list; # returns a reference to array @list } my $resultsRef = findLines();

How do I reference an array in Perl?

Creating a reference to a Perl array If we have an array called @names, we can create a reference to the array using a back-slash \ in-front of the variable: my $names_ref = \@names;. We use the _ref extension so it will stand out for us that we expect to have a reference in that scalar.


3 Answers

my $item = (function_returning_list())[0];

Functions cannot return arrays, they can return the contents of an array (i.e. a list). Lists are indexed starting at 0, so the first item of a function's return is (func)[0]. You could also say

my ($item) = function_returning_list();

This puts function_returning_list in list context and does assignment (in order) to the variables in the left-hand-side list.

It is important to note that

sub function_returning_list {
    return ("a", "b", "c")
}

my $item = function_returning_list();

will likely not do what you expect. The $item variable will be assigned "c". This is because there is no such thing as a list in scalar context. Instead, you have the comma operator in scalar context, and that evaluates the lefthand expression in void context, discards the result, then evaluates the righthand side in scalar context.

I call a sequence (rather than a list) and is useful if a few situations like C-style for loops.

like image 116
Chas. Owens Avatar answered Nov 15 '22 08:11

Chas. Owens


First, [1] is the second item in the list since Perl uses 0-based indices.

Second, you need the function's return to be evaluated in list context in order to have a list to access.

(functionReturningArray())[0]
like image 44
jamessan Avatar answered Nov 15 '22 07:11

jamessan


Going one step further than the discussion below Chas's answer, there's no such thing as a list period.

Unlike Python which has the tuple type filling this role, Perl's lists are entirely a construct of the stacks in the compiler/interpreter. This is why you can not take a reference to a list.

Just like python's use of tuples, perl automatically pushes and shifts its stack to move around groups of variables when a construct such as the = assignment operator is used. (Perl's precedence rules are what require the parenthesis, since = binds tighter than ,). The macro level difference between Perl's and Python's mechanisms is that context propagates through the entire expression.

So when in scalar context, that context is distributed to each of the , operators and the operator executes its left side in void context and its right side in scalar context which it then returns. However in list context the , operator pushes its arguments onto the stack, all of which are executed in list context. The stack is then passed across the assignment operator and then shifted into the lvalue. The stack/list itself is immutable to Perl level code, it's modification tools are effectively all of Perl's syntax.

So while it is incorrect to refer to a list in scalar context (because such a thing can not happen), you can refer to the behavior of list like syntactic constructs (constructed by the , operator, constructed by an array slice or list slice). In scalar context, the behavior of list like constructs is to return the last element of the list. How this is achieved is up to the operators in the expression. this is of course in contrast to the behavior of arrays in scalar context which return their length.

To clarify with an example and finally obey the rules and actually answer the question:

Assuming my @array = (10, 11, 12);

  • scalar context

      my $val = (10, 11, 12);        # $val is 12
      my $val = (10 .. 20)[0 .. 5];  # $val is 15      
      my $val = @array;              # $val is 3
      my $val = function();          # $val is the last executed expression
    
    • so if function ends with 10, 11, 12 then the value will be 12
    • if it instead is @array then the value will be 3
    • and if it ends with 10, 11, 12, @array the value is also 3

  • list context

      my ($val) = (10, 11, 12);        # $val is 10
      my ($val) = (10 .. 20)[0 .. 5];  # $val is 10
      my ($val) = @array;              # $val is 10
      my ($val) = function();          # $val is the first executed expression
                                       # in the last statement.
    
    • so if function ends with 10, 11, 12 then the value will be 10
    • if it instead is @array then the value will be 10
    • and if it ends with 10, 11, 12, @array the value is also 10

  • and for completeness, list context grabbing the whole list into an array

      my @val = (10, 11, 12);        # @val is 10, 11, 12
      my @val = (10 .. 20)[0 .. 5];  # @val is 10, 11, 12, 13, 14, 15
      my @val = @array;              # @val is 10, 11, 12
      my @val = function();          # @val is the last executed statement
    
    • so if function ends with 10, 11, 12 then @val will be 10, 11, 12
    • if it instead is @array then @val will be 10, 11, 12
    • and if it ends with 10, 11, 12, @array then @val will be 10, 11, 12, 10, 11, 12
like image 28
Eric Strom Avatar answered Nov 15 '22 06:11

Eric Strom