() questions

M

Matija Papec

1) () stands afaik for "empty list", so why it doesn't pass a map function?
Is such behavior accidental or intentional?

print join ',', map $_%2 ? () : $_, 1..20;


2) how to grok this expression, what exactly perl does here?

my $count = () = $data =~ /match/g;

is this /on the perl side/ same as,
my $count = @{[ $data =~ /match/g ]};

?
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

1) () stands afaik for "empty list", so why it doesn't pass a map
function? Is such behavior accidental or intentional?

print join ',', map $_%2 ? () : $_, 1..20;

I do not understand what you mean by "pass a map function". The above
statement prints "2,4,6,8,10,12,14,16,18,20", which makes perfect sense
to me. What is puzzling you about it?

2) how to grok this expression, what exactly perl does here?

my $count = () = $data =~ /match/g;

This is a semi-cheesy way of getting a list context on the right side of
the expression and a scalar context on the left side. In a list context,
m//g gives a list of all matching substrings. The left side, $count, is
in scalar context, which yields the number of substrings.

is this /on the perl side/ same as,
my $count = @{[ $data =~ /match/g ]};

Effectively, yes, although imho the former syntax is easier to
understand.

- --
Eric
$_ = reverse sort $ /. r , qw p ekca lre uJ reh
ts p , map $ _. $ " , qw e p h tona e and print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBP23Pd2PeouIeTNHoEQJhAgCgzevmNG1kxbe75DZcfCuyYbZBkEgAoJ87
JK9Sr0ShjX0dAsB1BgIF6iyd
=dmfV
-----END PGP SIGNATURE-----
 
S

Steve Grazzini

Matija Papec said:
1) () stands afaik for "empty list", so why it doesn't pass
a map function? Is such behavior accidental or intentional?

print join ',', map $_%2 ? () : $_, 1..20;

This *is* an empty list. The map() expression returns an empty
list for the odd members of the input, kind of like grep().

print join ',', grep { not $_ % 2 } 1..20;
2) how to grok this expression, what exactly perl does here?

my $count = () = $data =~ /match/g;

is this /on the perl side/ same as,
my $count = @{[ $data =~ /match/g ]};

No -- there's no array. This is list assignment in scalar
context, as documented in perlop.

Similarly, a list assignment in list context produces the
list of lvalues assigned to, and a list assignment in
scalar context returns the number of elements produced
by the expression on the right hand side of the assignment.

So the result is the same, but for a different reason.
 
J

John W. Krahn

Matija said:
1) () stands afaik for "empty list", so why it doesn't pass a map function?
Is such behavior accidental or intentional?

print join ',', map $_%2 ? () : $_, 1..20;

$ perl -le'print join ",", map $_%2 ? () : $_, 1..20;'
2,4,6,8,10,12,14,16,18,20

It works fine here. What problems are you having?

2) how to grok this expression, what exactly perl does here?

my $count = () = $data =~ /match/g;

is this /on the perl side/ same as,
my $count = @{[ $data =~ /match/g ]};

The first one uses a list to get the count and the second one uses an
array. I would assume, but I don't know for sure, that populating and
dereferencing an array would be less efficient then using a list.


John
 
M

Matija Papec

X-Ftn-To: Eric J. Roode
I do not understand what you mean by "pass a map function". The above

"Passing a map" is what happens to $_ when it gets transformed by map (from
right to left).
statement prints "2,4,6,8,10,12,14,16,18,20", which makes perfect sense
to me. What is puzzling you about it?

Well, map is a function which transforms list of values, so one could
expect[1] at least one value on the left side of map, for each element
coming from right. In case of empty list, () nothing gets through..?
This is a semi-cheesy way of getting a list context on the right side of
the expression and a scalar context on the left side. In a list context,
m//g gives a list of all matching substrings. The left side, $count, is
in scalar context, which yields the number of substrings.

This forcing of list context looks easier then @{[]} but who can tell if
newer perls will support it?


[1] at least on the 'do what I mean' basis :)
 
M

Matija Papec

X-Ftn-To: John W. Krahn

John W. Krahn said:
$ perl -le'print join ",", map $_%2 ? () : $_, 1..20;'
2,4,6,8,10,12,14,16,18,20

It works fine here. What problems are you having?

See my post to Eric.
2) how to grok this expression, what exactly perl does here?

my $count = () = $data =~ /match/g;

is this /on the perl side/ same as,
my $count = @{[ $data =~ /match/g ]};

The first one uses a list to get the count and the second one uses an
array. I would assume, but I don't know for sure, that populating and
dereferencing an array would be less efficient then using a list.

Tnx, I'll try benchmark.
 
M

Matija Papec

X-Ftn-To: Abigail

Abigail said:
][ 2) how to grok this expression, what exactly perl does here?
][
][ my $count = () = $data =~ /match/g;

Perl does a little strange here. It matches /match/ against $data,
repeatedly, and, because it's in list context, it returns a list
of the matches (since there are no parens in /match/).

But the list itself is in scalar context. Now, we all like to chant
that there are no lists in scalar context, but this one is. And
apparently, a list in scalar context returns the number of elements
in the list.

However, I doubt this is documented.

Really don't have a clue, I didn't saw it till recently..
][ is this /on the perl side/ same as,
][ my $count = @{[ $data =~ /match/g ]};

Sort of. Except that instead of a list, we have an array in scalar
context. And that behaviour is well defined.

Err, any suggestion for perldoc RTFM? :)
 
S

Steve Grazzini

Matija Papec said:
Eric J. Roode wrote
Matija Papec <[email protected]> wrote:

Well, map is a function which transforms list of values, so one could
expect[1] at least one value on the left side of map, for each element
coming from right. In case of empty list, () nothing gets through..?

That's right. The block (or expression) yields a *list* of values
for each element in the input list. A common idiom for creating
hashes transforms each input element into a key/value pair:

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

Returning one element is probably more common, but returning an empty
list makes sense too. It has the effect of "filtering"... in your case,
though, grep() would work just as well, since you're not actually
transforming the elements you keep.
This is a semi-cheesy way of getting a list context on the right side of
the expression and a scalar context on the left side. In a list context,
m//g gives a list of all matching substrings. The left side, $count, is
in scalar context, which yields the number of substrings.

This forcing of list context looks easier then @{[]} but who can tell if
newer perls will support it?

All bets are off with Perl 6, but the current behavior of list
assignment in scalar context is documented in perlop and widely used
(although not necessarily well-understood) so it's extremely unlikely
to disappear from Perl 5.
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

X-Ftn-To: Eric J. Roode
I do not understand what you mean by "pass a map function". The above

"Passing a map" is what happens to $_ when it gets transformed by map
(from right to left).
statement prints "2,4,6,8,10,12,14,16,18,20", which makes perfect
sense to me. What is puzzling you about it?

Well, map is a function which transforms list of values, so one could
expect[1] at least one value on the left side of map, for each element
coming from right. In case of empty list, () nothing gets through..?

Right. Try this:

@a = (1, 2, 3, (), 5, 6, (), 7);

The ()s disappear, because the list on the right-hand side is
"flattened" as it is evaluated. Were you perhaps expecting them to be
undef? undef is a scalar value. Or perhaps an empty anonymous array
ref, like []? That too is a scalar value.

- --
Eric
$_ = reverse sort $ /. r , qw p ekca lre uJ reh
ts p , map $ _. $ " , qw e p h tona e and print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBP288ZWPeouIeTNHoEQIsUwCfRs4cEA/hYF/HVB6JmlXiqOdI/HIAnAnx
ULswnFpR+7mOCcDku+M2zIHY
=CFV0
-----END PGP SIGNATURE-----
 
D

Darren Dunham

Matija Papec said:
X-Ftn-To: Eric J. Roode
Well, map is a function which transforms list of values, so one could
expect[1] at least one value on the left side of map, for each element
coming from right. In case of empty list, () nothing gets through..?

An empty list does not take up a slot in a list.

The list ("a", (), "b", (), "c") has 3 elements.
The list ("a", "", "b", "", "c") has 5 elements.

perl -e '@a = ("a", (), "b", "c"); print "$a[1]\n"
 
A

Anno Siegel

Matija Papec said:
X-Ftn-To: Eric J. Roode
I do not understand what you mean by "pass a map function". The above

"Passing a map" is what happens to $_ when it gets transformed by map (from
right to left).
statement prints "2,4,6,8,10,12,14,16,18,20", which makes perfect sense
to me. What is puzzling you about it?

Well, map is a function which transforms list of values, so one could
expect[1] at least one value on the left side of map, for each element
coming from right. In case of empty list, () nothing gets through..?

The idea that list elements "pass map" in some sense to build the result
list is not a useful visualization of the process.

The map operator evaluates the block (or expression) in list context, once
for each list element, and flattens the resulting lists into one big one.
If the block returns an empty list on some occasions, the result list doesn't
grow on that step.

"map" also sets $_ to each list element in turn, and the block can make
use of that, but that's no requirement. It can entirely ignore the original
list elements. Seen like that, they certainly don't "pass through map".
This is a semi-cheesy way of getting a list context on the right side of
the expression and a scalar context on the left side. In a list context,
m//g gives a list of all matching substrings. The left side, $count, is
in scalar context, which yields the number of substrings.

This forcing of list context looks easier then @{[]} but who can tell if
newer perls will support it?

It's documented behavior (in perldata), and fundamental idioms rely on
it, like "while ( my( $key, $val) = each %hash ) {". It isn't likely
to go away.

Anno
 
C

ctcgag

Matija Papec said:
X-Ftn-To: Eric J. Roode
I do not understand what you mean by "pass a map function". The above

"Passing a map" is what happens to $_ when it gets transformed by map
(from right to left).
statement prints "2,4,6,8,10,12,14,16,18,20", which makes perfect sense
to me. What is puzzling you about it?

Well, map is a function which transforms list of values, so one could
expect[1] at least one value on the left side of map, for each element
coming from right. In case of empty list, () nothing gets through..?

Exactly right. Nothing, i.e. the empty list, gets through. If you
want something to get through, you should pass something, like undef.


Xho
 
M

Matija Papec

X-Ftn-To: Eric J. Roode

Eric J. Roode said:
"Passing a map" is what happens to $_ when it gets transformed by map
(from right to left).
statement prints "2,4,6,8,10,12,14,16,18,20", which makes perfect
sense to me. What is puzzling you about it?

Well, map is a function which transforms list of values, so one could
expect[1] at least one value on the left side of map, for each element
coming from right. In case of empty list, () nothing gets through..?

Right. Try this:

@a = (1, 2, 3, (), 5, 6, (), 7);

The ()s disappear, because the list on the right-hand side is
"flattened" as it is evaluated. Were you perhaps expecting them to be
undef? undef is a scalar value. Or perhaps an empty anonymous array
ref, like []? That too is a scalar value.

Right, I'm expecting something (I know it can't be scalar), but I'm for sure
expecting something! :D

Tnx for explanation.
 
M

Matija Papec

X-Ftn-To: Steve Grazzini

Steve Grazzini said:
That's right. The block (or expression) yields a *list* of values
for each element in the input list. A common idiom for creating
hashes transforms each input element into a key/value pair:

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

Returning one element is probably more common, but returning an empty
list makes sense too. It has the effect of "filtering"... in your case,
though, grep() would work just as well, since you're not actually
transforming the elements you keep.

Right now I'm tempted to start coding using only map since grep is obviously
redundant in Perl. ;)
 
M

Matija Papec

X-Ftn-To: Anno Siegel

expect[1] at least one value on the left side of map, for each element
coming from right. In case of empty list, () nothing gets through..?

The idea that list elements "pass map" in some sense to build the result
list is not a useful visualization of the process.

The map operator evaluates the block (or expression) in list context, once
for each list element, and flattens the resulting lists into one big one.
If the block returns an empty list on some occasions, the result list doesn't
grow on that step.

"map" also sets $_ to each list element in turn, and the block can make
use of that, but that's no requirement. It can entirely ignore the original
list elements. Seen like that, they certainly don't "pass through map".

Hm true; I usually use that sort of visualization to catch on longer
expressions.
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Right now I'm tempted to start coding using only map since grep is
obviously redundant in Perl. ;)

There's some book or documentation example (I've forgotten the source),
which shows that map and grep can easily be rewritten in terms of the
other:

@a = map f($_), @b; # is the same as
@a = grep {$_ = f($_); 1} @b;

@a = grep f($_), @b; # is the same as
@a = map f($_)? $_ : (), @b;

Just a cute bit of trivia. :)

- --
Eric
$_ = reverse sort $ /. r , qw p ekca lre uJ reh
ts p , map $ _. $ " , qw e p h tona e and print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBP3D5A2PeouIeTNHoEQKy1QCg9+aheWQ+aSB2KrCWPK68Xpt4OvwAoLRb
b0oly5y76SH8vzepgAgct9Y8
=BLH3
-----END PGP SIGNATURE-----
 
P

Philip Newton

Matija Papec ([email protected]) wrote on MMMDCLXXIII September MCMXCIII
in <URL:][
][ 2) how to grok this expression, what exactly perl does here?
][
][ my $count = () = $data =~ /match/g;

Perl does a little strange here. It matches /match/ against $data,
repeatedly, and, because it's in list context, it returns a list
of the matches (since there are no parens in /match/).

But the list itself is in scalar context. Now, we all like to chant
that there are no lists in scalar context, but this one is. And
apparently, a list in scalar context returns the number of elements
in the list.

The way I interpret it, it's not a *list* in scalar context, but a *list
assignment* in scalar context.
However, I doubt this is documented.

It's in perlvar:

List assignment in scalar context returns the number of
elements produced by the expression on the right side of
the assignment:

Newer versions even have, after that, a little bit about how this
applies to code like

$count = () = $string =~ /\d+/g;

(the example in perlvar that belongs to the explanation).

It's basically an extension of the fact that "$count = (($foo, $bar) =
localtime;" puts 9 into $count, even though only two values were
assigned, since nine values were on the right-hand side of the
assignment.

Cheers,
Philip
 

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

Forum statistics

Threads
474,139
Messages
2,570,805
Members
47,356
Latest member
Tommyhotly

Latest Threads

Top