Despertar
Despertar

Reputation: 22362

Convert array to list

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

Answers (5)

user5354397
user5354397

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

brian d foy
brian d foy

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

7stud
7stud

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

user2404501
user2404501

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

Sean
Sean

Reputation: 29772

Functions can use wantarray to determine the context they're in and return something accordingly:

sub get_array {
    my @a = ("one", "two");
    return wantarray ? @a : $a[-1];
}

Upvotes: 5

Related Questions