microbe
microbe

Reputation: 2169

Perl map passing arguments

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

Answers (2)

Mark Dominus
Mark Dominus

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

TLP
TLP

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

Related Questions