tags:

views:

275

answers:

3

I have a problem in Perl I don't understand. I stripped it down to this very short code.

Why does Perl's map function return an empty array? Shouldn't it return an array with 9 undefs?

sub mySub{
    return;
}

my @arr = (1 .. 9);
my @arr2 = map( mySub($_), @arr );

print @arr . ' ' . @arr2, "\n";

It prints "9 0".

It is probably something simple, but perldoc is not helping.

+7  A: 

You subroutine is not returning undef, it is returning an empty list. 9 times and empty list is still an empty list.

Try explicitly returning undef and the output will be different.

innaM
No, you would get a list of 9 empty lists.
jiggy
yes, that's it, thanks.
Karel Bílek
jiggy: I think you cannot have a list of lists in perl. Perl lists are all "flat" and "1-dimensional".
Karel Bílek
@karel, Perl can nest data structures to arbitrary depth and complexity (see http://perldoc.perl.org/perldsc.html). Secondly, while Manni's answer (surprisingly) does give the desired output, it doesn't work the way you think. Run this: my @arr2 = map(undef, @arr); and you will get the same result.
jiggy
The same as what? You'll get an array containing undef 9 times.
innaM
jiggy: Yes, perl has n-dimensional lists, but it order to get that you'd have to return a list reference from mySub, eg "return [];", because otherwise the lists get flattened.
JSBangs
Who's talking about more than 1 dimension here?
innaM
Very fair. Thanks.
innaM
@Manni, yeah I know about list flattening, but I concede that I messed up here. Your answer does work. I always use map with a block, so the syntax looked wrong to me, but it ain't.
jiggy
jiggy: my subroutine is actually bigger than this one and it would feel wrong to put it just to block. Also, it returned empty lists (which I thought was undef) only is some cases, so the result was not empty array but only smaller array. Anyway thanks both
Karel Bílek
+2  A: 

Try this

use strict;
use warnings;

sub mySub{
    return undef;
}

my @arr = (1,2,3,4,5,6,7,8,9);
my @arr2 = map(&mySub, @arr);

print @arr." ".@arr2;

If you need to get list containing undefs, you need to return undef explicitly. The thing is that map calls your mySub in array context (check what wantarray gives you from this sub). return statement essentially gives back an empty list each time your sub is called, which results in empty array in total

zakovyrya
nonono, my code was just a stupid example that did nothing. I don't want to do what you described, I just wanted to have list with 9 undefs. But thanks anyway
Karel Bílek
Why is this downmodded? This is the most sensible answer here.
jrockway
+6  A: 

The more general answer to your question is this: when return is used without an argument, the value it returns depends on the calling context:

list context    returns an empty list
scalar context  returns an undefined value

For example:

use strict;
use warnings;
use Data::Dumper;

my (@list);
sub mySub { return }
@list = map(       mySub($_), 1..2); print Dumper(\@list);
@list = map(scalar mySub($_), 1..2); print Dumper(\@list);

Output:

$VAR1 = [];
$VAR1 = [
          undef,
          undef
        ];
FM
thanks .... the catch is, I didn't know that map calls it in list context.(this scalar/list context concept still sometimes confuse me in perl :))
Karel Bílek