Can explain the MAP function more clearly? Thanks

Y

yezi

Hi :
I am confused with the sentence "

%seq_nos_set=map{$_=> 1} @seq_nos

Thanks for any information.

what is {$_=> 1 } mean?
 
A

A. Sinan Unur

Hi :
I am confused with the sentence "

%seq_nos_set=map{$_=> 1} @seq_nos

Thanks for any information.

what is {$_=> 1 } mean?

Have you read the documentation?

From perldoc -f map:

%hash = map { getkey($_) => $_ } @array;

is just a funny way to write

%hash = ();
foreach $_ (@array) {
$hash{getkey($_)} = $_;
}

so

my %seq_nos_set = map{$_ => 1} @seq_nos;

is another way of writing:

my %seq_nos_set;
$seq_nos_set{$_} = 1 for @seq_nos;

Sinan
 
P

Paul Lalli

yezi said:
Hi :
I am confused with the sentence "

%seq_nos_set=map{$_=> 1} @seq_nos

Thanks for any information.

what is {$_=> 1 } mean?

{ } indicates a block
=> is a fancy way of writing a comma

So { $_ => 1 } is a block that returns a 2-element list ($_, 1)

map() takes this block and evaluates it for each element of @seq_nos
(each time setting $_ to the current element of @seq_nos). Each
evaluation of the block is then added to %seq_nos_set. Therefore
%seq_nos_set will be a hash (which is a list of key/value pairs) where
all the keys are elements of @seq_nos, and all the values are 1.

Paul Lalli
 
D

David K. Wall

A. Sinan Unur said:
my %seq_nos_set = map{$_ => 1} @seq_nos;

is another way of writing:

my %seq_nos_set;
$seq_nos_set{$_} = 1 for @seq_nos;


@seq_nos_set{@seq_nos} = (1) x @seq_nos;

is the way I tend to write something like this. I'm not sure exactly
WHY I got into that habit, though.
 
A

A. Sinan Unur

@seq_nos_set{@seq_nos} = (1) x @seq_nos;

is the way I tend to write something like this. I'm not sure exactly
WHY I got into that habit, though.

I find it very visually appealing. That might explain it :)
 
E

Eric Schwartz

Tad McClellan said:
It means the same as

{$_, 1 }

Every now and then I learn something new about Perl that is so basic.
I had mentally tagged => as "quote LHS, and then act as comma"; your
comment prompted me to look up perlop, which said,

If the argument on the left is not a word, it is first
interpreted as an expression, and then the string value
of that is used.

It's always nice when I can learn something new about something I
thought I understood already.

-=Eric
 
T

T Beck

Paul said:
{ } indicates a block
=> is a fancy way of writing a comma

So { $_ => 1 } is a block that returns a 2-element list ($_, 1)


Forgive me if I'm wrong, but in this case, wouldn't {} refer to an
anonymous hash?

--T Beck
 
E

Eric Schwartz

T Beck said:
Forgive me if I'm wrong, but in this case, wouldn't {} refer to an
anonymous hash?

This is in the context of the map function, so you should look at

perldoc -f map

To verify your assumption is correct.

map BLOCK LIST
map EXPR,LIST

So map takes either a BLOCK or an EXPR, and in this case it's a block.

"Wait a second," I hear you saying. "Doesn't { ... } make a hashref?"

Yes, it does-- but it also makes a block. Consider this:

sub foo
{
print "Hi, mom!\n";
}

Do the { } there make a hashref? No. Why? Because Perl can usually
tell whether you want a block or not. Offhand I can't think of a case
where it's ambiguous, but I'm sure someone else can.

-=Eric
 
P

Paul Lalli

T said:
Forgive me if I'm wrong, but in this case, wouldn't {} refer to an
anonymous hash?

Only when you (rather rudely, IMHO) snip the appropriate context.

my %hash = map { $_ => 1 } @foo;

{ $_ => 1 } is the block (or anonymous subroutine) that's passed as the
first argument to map. This block returns a two element list.

If the code was something along the lines of
my $hash_ref = { $_ => 1 };

then the braces would, indeed, create an anonymous hashref.

map()'s prototype, effectively, is:
sub map(&@);
which, perldoc perlsub tells us: "An & requires an anonymous
subroutine, which, if passed as the first argument, does not require
the sub keyword or a subsequent comma"

For more information:
perldoc -f map

Paul Lalli
 
X

xhoster

Eric Schwartz said:
This is in the context of the map function, so you should look at

perldoc -f map

To verify your assumption is correct.

map BLOCK LIST
map EXPR,LIST

So map takes either a BLOCK or an EXPR, and in this case it's a block.

"Wait a second," I hear you saying. "Doesn't { ... } make a hashref?"

Yes, it does-- but it also makes a block. Consider this:

sub foo
{
print "Hi, mom!\n";
}

Do the { } there make a hashref? No. Why? Because Perl can usually
tell whether you want a block or not. Offhand I can't think of a case
where it's ambiguous, but I'm sure someone else can.

I'm not sure what you mean about being ambiguous. Before perl
disambiguates the construct, it is always ambiguous. After it does so, it
is never ambiguous (but it might be wrong). The interesting thing is, it
guesses what you want before looking at the (lack of) comma.

map {$_=>1} @data;
block.

map {$_=>1}, @data;
block, syntax error (but if it disambiguated to hashref, then would not be
syntax error

map +{$_=>1}, @data;
hash ref.

map +{$_=>1} @data;
hash ref, syntax error
 
T

T Beck

Paul said:
Only when you (rather rudely, IMHO) snip the appropriate context.

Sorry about the rudeness, I snipped it that way because I thought you
were trying to draw attention to the {$_=>1} {without} the map in
front. Deconstructing the problem, as it were.. No offense intended.
my %hash = map { $_ => 1 } @foo;

{ $_ => 1 } is the block (or anonymous subroutine) that's passed as the
first argument to map. This block returns a two element list.

If the code was something along the lines of
my $hash_ref = { $_ => 1 };

then the braces would, indeed, create an anonymous hashref.

map()'s prototype, effectively, is:
sub map(&@);
which, perldoc perlsub tells us: "An & requires an anonymous
subroutine, which, if passed as the first argument, does not require
the sub keyword or a subsequent comma"

For more information:
perldoc -f map


Thanks for clearing that up. I had a feeling that I was missing
something, but every once in a while I get lucky and get something
right. This wasn't one of those times tho. Thanks to Xho and Eric for
their responses, as well. Quite insightful.

--T Beck
 
E

Eric Schwartz

I'm not sure what you mean about being ambiguous. Before perl
disambiguates the construct, it is always ambiguous. After it does so, it
is never ambiguous (but it might be wrong).

Well, I'd hope so, or it wouldn't be disambiguating, would it? :) I
meant that as far as I know, Perl will always decide it's one thing or
t'other; I don't know of any situation where Perl will give up and
say, "I don't know if I should treat this as a code block or a
hashref."

-=Eric
 
H

Heinrich Mislik

@seq_nos_set{@seq_nos} = (1) x @seq_nos;

For me, this has two drawbacks:

1. It gets clumsy with strict:

my @seq_nos_set{@seq_nos} = (1) x @seq_nos;

gives Syntax error. One needs:

my %seq_nos_set;
@seq_nos_set{@seq_nos} = (1) x @seq_nos;

2. With a constant list you won't know the count:

@seq_nos_set{qw(foo bar hinz kunz)} = (1) x 100;

Any other elegant ways to create such hashes?

Greetings

Heinrich
 
C

ced

Heinrich said:
For me, this has two drawbacks:

1. It gets clumsy with strict:

my @seq_nos_set{@seq_nos} = (1) x @seq_nos;

gives Syntax error. One needs:

my %seq_nos_set;
@seq_nos_set{@seq_nos} = (1) x @seq_nos;

2. With a constant list you won't know the count:

@seq_nos_set{qw(foo bar hinz kunz)} = (1) x 100;

Any other elegant ways to create such hashes?

my %seq_nos_set = map { ($_, 1) } @seq_nos;

# my %seq_nos_set = map { ($_, 1) } qw/foo bar hinz kunz/;
 
B

Bart Lateur

yezi said:
%seq_nos_set=map{$_=> 1} @seq_nos
what is {$_=> 1 } mean?

It is a block of code that returns a list of two items:

($_, 1)

So for each item in the source list, this block is called, with $_ the
value of the current item, and this block returns a list with these two
values for each item. In the end, map will return a total list with 2
times as many items as the source list.

HTH,
Bart.
 
B

Bart Lateur

Heinrich said:
2. With a constant list you won't know the count:

@seq_nos_set{qw(foo bar hinz kunz)} = (1) x 100;

Any other elegant ways to create such hashes?

my %seq_nos_set;
$seq_nos_set{$_} = 1 foreach qw(foo bar hinz kunz);
 
B

Bart Lateur

Eric said:
Well, I'd hope so, or it wouldn't be disambiguating, would it? :)

But Perl occasionally *is* ambiguous. Witness this silly example:

{ $_ => 1 };

Is this a block, or a hashref in void context?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top