Perl, unknown result of the `map` function

Viewed 122

I get a very strange result in print @squares array below; I should have got 49 but I get some random number:

@numbers={-1,7};

my @squares = map { $_ > 5 ? ($_ * $_) : () } @numbers;

print @squares;

$ perl g.pl

12909907697296

2 Answers

This is incorrect:

@numbers={-1,7};

{ } builds a hash and returns a reference to the hash. The above is equivalent to

my %anon = ( -1 => 7 );
@numbers = \%anon;

A reference treated as a number returns the underlying pointer as a number, so you get garbage.


To populate an array, use

my @numbers = ( -1, 7 );

-1, 7 returns two numbers, which are added to the array when assigned to the array. (The parens aren't special; they just override precedence like in math.)


The complete program:

use 5.014;      # ALWAYS use `use strict;` or equivalent! This also provides `say`.
use warnings;   # ALWAYS use `use warnings;`!

my @numbers = ( -1, 7 );

my @squares = map { $_ > 5 ? ($_ * $_) : () } @numbers;

# Print each number on a separate line.
# Also provides the customary final line feed.
say for @squares;

Alternative:

my @squares =
   map { $_ * $_ }
      grep { $_ > 5 }
         @numbers;

Your line @numbers={-1,7} does not create a list of multiple integers. In Perl, an expression with curly braces denotes a hash reference literal. This could be written more clearly as:

my @numbers = ({ "-1" => 7 });

So that is a list of one item, which is a hash reference.

Later, you use the hash reference as a number. When you use a reference as a number, it is converted to its memory address, which is some unspecified large number. That is what you're seeing.

To create an inclusive range in Perl, use the .. operator:

my @numbers = -1..7;

To just spell out all items in a list, enclose it in parentheses ( ):

my @numbers = (-1, 7);
Related