Reputation: 22362
sub get_list {
return ("one", "two");
}
sub get_array {
my @a = ("one", "two");
# need to convert @a to list
return @a;
}
my $two = get_list(); # desired, assigns last item in list to scalar
my $count = get_array(); # evaluates array in scalar context, returning a count
In the get_array() method, I already have an array created, but I want to return it as a list so that it assigns according to list rules and not array rules. The array of course would normally be built in a more complex way (not directly from a list).
I have tried using map in hopes that it would return me a list of values, but this gives the same results. Same with split/join.
return map { $_ } @a;
return split /,/, join(",", @a);
How can I convert the array into a list of values?
Upvotes: 3
Views: 5181
Reputation:
I needed a list of variables. Maybe somebody else needs that, too:
my $start = 0;
my $length = 10;
my $database = "foo";
my $chapter = "bar";
my @sql_wheres = ();
push(@sql_wheres, "database LIKE ?") if ($database);
push(@sql_wheres, "chapter LIKE ?") if ($chapter);
# more code here to use DBI and initilize $select
$select->execute( (@wheres), $start, $length );
Without the round brackets around (@wheres) it did not work. But with the round brackets the variables where supplied as a list.
Upvotes: -2
Reputation: 132775
Curiously, the answers focused on the stuff in the subroutine instead of giving you the proper answer. If you want list behavior, do list operations. Perl largely decides how to treat things based on what you are doing, so be comfortable telling Perl how to treat data rather than relying on tricks to make it work out.
In your case, assign to a list:
my( $item ) = get_list();
my( $item ) = get_array();
Those both return the first item because there is only one variable on the lefthand side and the lefthand list simply ignores the remaining items from the righthand list.
If you wanted the second item but not the first or third, you can use undef
as a placeholder:
my( undef, $item ) = get_list();
I hardly ever do that because a slice is easier:
my $item = (get_list())[1];
If you want the last items, take a list slice and count backward from the end with a negative subscript:
my $item = (get_list())[-1];
my $item = (get_array())[-1];
And, if you are the one creating those subroutines and you only want the last item in the list, don't return a list at all. Simply return the value you want. You'll notice that Perl does this for many of its builtin functions (localtime
, get*
, and so on).
Here are some more examples:
use v5.10;
my( undef, undef, $mode ) = stat('/etc/hosts');
printf "mode is %o\n", $mode;
say "Hour is ", (localtime)[2];
say "User is " . getpwuid(501); # concatenation, so scalar context
my $name = getpwuid(501); # scalar assignment, so scalar context
say "User is $name";
my $uid = (getpwnam($name))[2];
say "UID is $uid";
Upvotes: 0
Reputation: 48599
See perlop comma operator
:
Binary "," is the comma operator. In scalar context it evaluates its left argument, throws that value away, then evaluates its right argument and returns that value. This is just like C's comma operator.
And see perldata list value constructors
:
In a context not requiring a list value, the value of what appears to be a list literal is simply the value of the final element, as with the C comma operator. For example,
@foo = ('cc', '-E', $bar);
assigns the entire list value to array @foo, but
$foo = ('cc', '-E', $bar);
assigns the value of variable $bar to the scalar variable $foo. Note that the value of an actual array in scalar context is the length of the array;
From the map docs:
map EXPR,LIST
Evaluates the BLOCK or EXPR for each element of LIST (locally setting $_ to each element) and returns the list value composed of the results of each such evaluation.
Perfect! Just what you want:
my @arr = ('a', 'b', 'c');
my $result = map "-->$_<--", @arr;
say $result; #=>3 ???
Boo, hoo:
In scalar context, [map] returns the total number of elements so generated.
So, after reading Sean's answer you can surmise that map()
is defined to do the equivalent of the following:
return wantarray ? (result1, result2,...,resultN) : N;
Same thing for split:
Splits the string EXPR into a list of strings and returns the list in list context, or the size of the list in scalar context.
Upvotes: -1
Reputation:
The answer with wantarray
makes the intent explicit, which is good. But if you want something that looks more like magic which you can refer to as "listifying the array" to confuse and impress people, a slice will do it:
return @a[0..$#a];
Upvotes: 4