Reputation: 2169
I'm trying map() with my own subroutine. When I tried it with a Perl's builtin function, it works. But when I tried map() with my own subroutine, it fails. I couldn't point out what makes the error.
Here is the code snippet.
#!/usr/bin/perl
use strict;
sub mysqr {
my ($input) = @_;
my $answer = $input * $input;
return $answer;
}
my @questions = (1,2,3,4,5);
my @answers;
@answers = map(mysqr, @questions); # doesn't work.
@answers = map {mysqr($_)} @questions; #works.
print "map = ";
print join(", ", @answers);
print "\n";
Upvotes: 4
Views: 1049
Reputation: 1808
Map always assigns an element of the argument list to $_
, then evaluates the expression. So map mysqr($_), 1,2,3,4,5
calls mysqr
on each of the elements 1,2,3,4,5, because $_
is set to each of 1,2,3,4,5 in turn.
The reason you can often omit the $_
when calling a built-in function is that many Perl built-in functions, if not given an argument, will operate on $_
by default. For example, the lc
function does this. Your mysqr
function doesn't do this, but if you changed it to do this, the first form would work:
sub mysqr {
my $input;
if (@_) { ($input) = @_ }
else { $input = $_ } # No argument was given, so default to $_
my $answer = $input * $input;
return $answer;
}
map(mysqr, 1,2,3,4,5); # works now
Upvotes: 6
Reputation: 67900
The difference is that in the second case, you are explicitly passing the argument, and in the first one, you pass nothing.
@answers = map(mysqr, @questions); # same as mysqr(), no argument passed
@answers = map {mysqr($_)} @questions; # $_ is passed on to $input
You might be thinking of the fact that many Perl built-in functions use $_
when no argument is given. This is, however, not the default behaviour of user defined subroutines. If you want that functionality, you need to add it yourself. Though be warned that it often is not a good idea.
Note that if you use use warnings
, which you always should, you will get a descriptive error:
Use of uninitialized value $input in multiplication (*) at foo.pl line 8.
Which tells you that no data is passed to $input
.
Not using warnings is not removing errors from your code, it is merely hiding them, much like hiding the "low oil" warning lamp in a car does not prevent engine failure.
Upvotes: 2