Readline using foreach and while

S

szr

Ben said:
OK, now explain to me why

my @ary = qw/a b c/;
print map { /c/ and push @ary, 'd'; $_ } @ary;

*doesn't* work like that :).

Ben

For starters, we were talking about for(LIST), not map.


perldoc -f map

map BLOCK LIST
map EXPR,LIST
Evaluates the BLOCK or EXPR for each element of LIST
[...]


It would seem map does not re-check the count of the list each time
around like for those, which sort of makes sense, as it's supposed to
eval the block/expression for "each element", which to me means each
elemt of the list originally passed to map.

"map" and "for"/"foreach" are two similar but different beasts :)
 
S

szr

Ben said:
OK, now explain to me why

my @ary = qw/a b c/;
print map { /c/ and push @ary, 'd'; $_ } @ary;

*doesn't* work like that :).

Actually it does. The difference is, map doesn't recheck the count every
time around like for/foreach do. If you print the contents of @ary after
the line with the map statement, it does indeed contain 'd' at the end.
This behavior seems to correct, as one would likely expect that the list
map returns when it is finished to be the same length as the one
/passed/ into map at the start. If you pass a 3 element list, you should
get back a 3 element list, should you not? Or do you consider this to be
a bug?

However, consider:

my @ary = qw/a b c/;
print map { /c/ and $_ = 'd'; $_ } @ary;


__OUTPUT__
abd

$_ is aliased to the current array element just like in for. Again, the
only difference I see if that map doesn't recheck the count of the
passed list for each iteration. Well, that and map returns a list :)

To me, this behavior is part of what separates map from for/foreach.
 
B

Ben Morrow

Quoth "szr said:
Actually it does. The difference is, map doesn't recheck the count every
time around like for/foreach do. If you print the contents of @ary after
the line with the map statement, it does indeed contain 'd' at the end.
This behavior seems to correct, as one would likely expect that the list
map returns when it is finished to be the same length as the one
/passed/ into map at the start. If you pass a 3 element list, you should
get back a 3 element list, should you not?

Absolutely not. my %h = map { $_ => 1 } qw/a b c/; is quite a common
idiom.

$_ is aliased to the current array element just like in for. Again, the
only difference I see if that map doesn't recheck the count of the
passed list for each iteration.

No, you're misunderstanding the difference between a list and an array.
Evaluating an array in list context returns a list of its elements *as
they are now*; under most circumstances, it returns a list of aliases to
those elements, but any changes to the order of the elements in @ary are
not propagated into the list. Consider

my @ary = qw/a b c/;
sub foo {
my @keep = map "$_", @_; # kill the aliasing
unshift @ary, 'h';
$_[$_] .= $keep[$_] for 0..$#_;
}
foo @ary;
print for @ary;
To me, this behavior is part of what separates map from for/foreach.

It separates for (LIST) from everything else that accepts a LIST. This is
why I called it 'weird'.

Ben
 
S

szr

Ben said:
Absolutely not. my %h = map { $_ => 1 } qw/a b c/; is quite a common
idiom.

Well, you're still getting that many *sets* which is probably what I
should of said, or have been clearer. In that example, you get 3 set of
hash pairs resulting from the 3 element list. The point is you get
count_of_passed_list amount of something from the map, in some form or
another. How exactly it's returned is determined by the template inside
the map.
No, you're misunderstanding the difference between a list and an
array. Evaluating an array in list context returns a list of its
elements *as they are now*;

I seem to understand it just fine. What we both said above seems to be
true. Maybe we're just misunderstanding what the other is trying to say?
:)
under most circumstances, it returns a
list of aliases to those elements, but any changes to the order of
the elements in @ary are not propagated into the list. Consider

my @ary = qw/a b c/;
sub foo {
my @keep = map "$_", @_; # kill the aliasing

Ok @keep now contains (a, b, c)...
unshift @ary, 'h';

@ary, which comes from a scope outside this sub, now contains (h, a, b,
c)
$_[$_] .= $keep[$_] for 0..$#_;

Keep in mind $_[0] *still* points to what used to be the first element
of @ary. Remember, the aliasing isn't to the *array* but to it's
*elements*. This is because when you normally pass args to a sub (e.g.,
do_something($x, $y); ), the aliasing is with $x and $y to $_[0] and
$_[1]. Passing an array just like passing that many scalars as are
elements in the array; each individual one gets aliased to the next
sequential element of @_ in the sub's scope.
}
foo @ary;
print for @ary;

Running this (with the last line as `print "$_\n" for @ary;` for
clarity) prints:

h
aa
bb
cc

Seems the changes propgated just fine to me. You pushed 'h' to the
beginning of @ary, then you effectively iterated from
$ary[1]..$ary[$#ary].

Map is the same way in that regard; $_ is an alias to an *element*
It separates for (LIST) from everything else that accepts a LIST.
This is why I called it 'weird'.

I still don't see what you consider weird about it. What does it do that
you don't expect it to do?
 
U

Uri Guttman

s> Well, you're still getting that many *sets* which is probably what I
s> should of said, or have been clearer. In that example, you get 3 set of
s> hash pairs resulting from the 3 element list. The point is you get
s> count_of_passed_list amount of something from the map, in some form or
s> another. How exactly it's returned is determined by the template inside
s> the map.

you are still missing the picture. map can return ANY number of elements
(not sets). it executes its expression/block once for each input element
but that can generate 0-?? elements which are appended to the return
list. there are no boundaries in those elements so there are no true
sets. if you return a reference which holds stuff you can force your own
boundaries and make sets. that is also a known map idiom. map generates
a new list from input from another list. the transformation can be
anything and isn't tied to how many input elements there are.

uri
 
S

szr

Uri said:
common >> idiom.

s> Well, you're still getting that many *sets* which is probably
what I s> should of said, or have been clearer. In that example, you
get 3 set of s> hash pairs resulting from the 3 element list. The
point is you get s> count_of_passed_list amount of something from
the map, in some form or s> another. How exactly it's returned is
determined by the template inside s> the map.

you are still missing the picture. map can return ANY number of
elements (not sets). it executes its expression/block once for each
input element but that can generate 0-?? elements which are appended
to the return list.

I understand, but still, whatever is being generated to the LHS of map,
it's done that many times are there are elements in the list on the RHS.
Is that fair to say?
there are no boundaries in those elements so there are no true sets.

I meant "set" in a very generic way. Not in the mathematical sense, but
in the sense that you get back something that can be group of something
on the LHS by the number of elements on the RHS of map. The `map { $_ =>
1 }` example gives you that many pairs, for example.
 
U

Uri Guttman

s> I understand, but still, whatever is being generated to the LHS of map,
s> it's done that many times are there are elements in the list on the RHS.
s> Is that fair to say?

no, i wouldn't say what is being generated. just what i previously said
happens. the CODE in the expression/block is executed ONCE for each
input element. then the collected list of those is returned. use the
correct terminology and you will get it easier.

s> I meant "set" in a very generic way. Not in the mathematical sense, but
s> in the sense that you get back something that can be group of something
s> on the LHS by the number of elements on the RHS of map. The `map { $_ =>
s> 1 }` example gives you that many pairs, for example.

but there are no 'pairs' in the list except by the context of assigning
the list to a hash. there is just a list of elements created by the
map. map doesn't know or care what happens to its generated list. so
calling them pairs is out of context. and as such there are no
boundaries (which pairs implies). map can generate ANY sort of list you
want. no sets or pairs or groups need to be created. a single list is
what you get and all you should care about. how you use that list is up
to the next part of the expression.

uri
 
S

szr

(Please use proper capitalization and such, it will make your replies
easier to read.)

Uri said:
each >> input element but that can generate 0-?? elements which are
appended >> to the return list.

s> I understand, but still, whatever is being generated to the LHS
of map, s> it's done that many times are there are elements in the
list on the RHS. s> Is that fair to say?

no, i wouldn't say what is being generated. just what i previously
said happens. the CODE in the expression/block is executed ONCE for
each input element. then the collected list of those is returned.
use the correct terminology and you will get it easier.

Well that's basically how I understand it. In fact it seems you
basically restated the same thing in a different way. 1) the expr/block
is executed once per cycle. Yep. 2) The end result is something that is
a grouping, whether singular (say, a simple list) or more complex (like,
say, a hash key/value pair), of the same amount of elements in the input
list.

I know using proper terminology is important, but I think understand
meaning as someone put it into their own words is also an important
skill. This is something I have to do quite frequently in my line of
work when dealing with many kinds of people regarding projects I work
on. Not all of them are as savvy with programming (or a specific
language like Perl) and often I have to use simpler terms to describe
things.
sets.

s> I meant "set" in a very generic way. Not in the mathematical
sense, but s> in the sense that you get back something that can be
group of something s> on the LHS by the number of elements on the
RHS of map. The `map { $_ => s> 1 }` example gives you that many
pairs, for example.

but there are no 'pairs' in the list except by the context of
assigning the list to a hash.

I'm sorry, but I really have to disagree here. A hash is essentially a
list divided into pairs (keys and values, respectively), and `map { $_
=> s> 1 }` is creating such a pair in a statement like that.
 
A

A. Sinan Unur

I understand, but still, whatever is being generated to the LHS of
map, it's done that many times are there are elements in the list
on the RHS. Is that fair to say?

If I understand you correctly, yeah, that's fine to say.

On the other hand, you might find the following example instructive:

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

my @result = map { split // } ( '5' x rand(10) ) ;

print Dumper \@result;

__END__

Note that, the RHS is always a single element list. On the other hand,
the number of elements in the result of map is variable. So, yes, the
operation inside the block is only carried out once, what you are
saying is fair in that sense, but the map operation can change the
length of the list in non-simplistic ways:

E:\Home\asu1\Src\Test> t1.pl
$VAR1 = [];

E:\Home\asu1\Src\Test> t1.pl
$VAR1 = [
'5',
'5',
'5',
'5',
'5',
'5',
'5'
];

E:\Home\asu1\Src\Test> t1.pl
$VAR1 = [
'5',
'5',
'5',
'5'
];

Sinan


--
A. Sinan Unur <[email protected]>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/
 
U

Uri Guttman

s> Well that's basically how I understand it. In fact it seems you
s> basically restated the same thing in a different way. 1) the expr/block
s> is executed once per cycle. Yep. 2) The end result is something that is
s> a grouping, whether singular (say, a simple list) or more complex (like,
s> say, a hash key/value pair), of the same amount of elements in the input
s> list.


you keep saying grouping and that is the wrong way to think about
it. drop that word from this concept. map generates ONE list. how it
gets there is irrelevent so there is no grouping.

s> I'm sorry, but I really have to disagree here. A hash is essentially a
s> list divided into pairs (keys and values, respectively), and `map { $_
s> => s> 1 }` is creating such a pair in a statement like that.
no. a hash creates the pairs when it is assigned a list. the map just
generates a list with no real 'pairs'. you may think they are there but
they are not pairs yet. you have to separate what the map does from what
the hash expects.

uri
 
S

szr

A. Sinan Unur said:
If I understand you correctly, yeah, that's fine to say.

On the other hand, you might find the following example instructive:

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

my @result = map { split // } ( '5' x rand(10) ) ;

print Dumper \@result;

__END__

Note that, the RHS is always a single element list. On the other hand,
the number of elements in the result of map is variable. So, yes, the
operation inside the block is only carried out once, what you are
saying is fair in that sense, but the map operation can change the
length of the list in non-simplistic ways:

Nice example. And yes, this does go with my point. Perhaps I should of
said, the number of elements on the RHS dictates how many passes map
will make. In this case, it's indeed once, where split creates the list
(in fact the map statement is obviously redundant, but I see your
point.)

Thanks.
 

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