Readline using foreach and while

B

Ben Bullock

The FAQ entry does not contain the phrase "read things into a list".

I'm extremely sorry but I really don't understand what you are talking
about. I originally wrote that "the foreach version seems to read
things into an array", then you posted the reference to the FAQ, then
I read it and tried to understand what you were saying. I assumed that
you meant that I should have written "the foreach version reads things
into a list". If that isn't what you meant, perhaps you could clarify?
Your original comment was fairly cryptic, and I spent quite a long
time trying to understand what you meant.
print reverse grep /a/, readdir DIR;

In the above example, where does grep() get its list from?

From "readdir DIR", presumably. You're not making much sense to me.
Could you please stop making cryptic comments and actually explain
what you're trying to say in a way which people who don't already know
what you are talking about can understand?
 
X

xhoster

Ben Bullock said:
If we can create lists, then there must be a data structures inside
Perl which represents those created lists.

Not necessarily. A list might exist at the Perl-programmer interface
and not at the Perl-perl interface.
Let's call it the "newly-
created list" data structure. There is also a data structure for
arrays, of course.

The list 1..5 might be represented in different data structures, depending
on how it is being used.

OK:

http://perldoc.perl.org/Tie/File.html

But it says very shortly into the documentation "The file is not
loaded into memory" and "Changes to the array are reflected in the
file immediately". So your statement about "reads a file into an
array" is wrong.

Only if an array is defined as being something in which is "in RAM".
I don't think that that is the case in Perl. So the file can be in
an array without being in RAM. A Perl array is a set of capabilities
and a syntax for accessing those capabilities.
It is not reading the file into an array. It is
making a file appear to be an array.

That is just nonsense. You don't have "open" file handles, either, Perl
just makes it look they are are. For that matter, files themselves
don't exist--the OS and the FS just cooperate to make it appear that way.
Heck, OSes don't even exist, the various components of the motherboard and
hard-drives just make it seem like they do.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
S

szr

comp.llang.perl.moderated said:
Actually, an array just holds scalars... or references which is a
special type of scalar.

Isn't it more correct to say that an array holds a *list* of scalars? If
so, then it seems what I originally said is correct; an *array's*
*value* is a list, which contains scalars (numbers, strings, and refs.)

That is, a scalar take a number, string, or ref. An array takes a list
(which isa collection of scalars.) And by that token I suppose one could
say a hash's value is an even numbered list (key => val pairs) of
scalars :)
 
S

szr

Ben said:
No, you're misunderstanding. A list is immutable *after it has been
created*.

I think a better way of thinking about it is, a list is the literal
value used by na array, just like 123 and "abc" are literal values used
by scalars and too themselves not modifiyable.

It's like how in c and c++ you could initalize an array with a literal
value
(eg, int squares[5] = {1, 4, 9, 16, 25} )

Scalar variables are interfaces to manipulate numbers & strings.
Arrays (and Hashes**) are interfaces to manipulate Lists.



** I kind of look at the *value* of a Hash as being a (even numbered)
List, much like it is for an Array. You just access the List
differently. Arrays, by ordinals. Hashes, by key.


Comments and critisms welcome.
 
S

szr

Ben said:
Quoth Frank Seitz <[email protected]>: [...]
use strict;
use warnings;

my @a = qw/a b c/;
for my $v (@a) {
push @a,'d' if $v eq 'c';
print "$v\n";
}

Good point. for is a little weird in this respect...

Nothing really weird about it. In that case above, it's no different
than:

for (my $i=0; $i<@a; $i++) {
my $v = $a[$i];
push @a,'d' if $v eq 'c';
print "$v\n";
}


In either case, it's going over the array, one element at a time, in
sequence, s oif you "push" something onto the end, it grows the array by
one and thus the for look keeps going.
 
C

comp.llang.perl.moderated

Isn't it more correct to say that an array holds a *list* of scalars? If
so, then it seems what I originally said is correct; an *array's*
*value* is a list, which contains scalars (numbers, strings, and refs.)

That is, a scalar take a number, string, or ref. An array takes a list
(which isa collection of scalars.) And by that token I suppose one could
say a hash's value is an even numbered list (key => val pairs) of
scalars :)

A purely semantic case can be made that an array contains a list.
However, internally Perl's "list" as discussed in this thread is just
a stack where values are stored/retrieved for the very limited
lifetime of a particular statement.
So I think it'd mis-charactrize an array to say it holds a list in the
sense of a ephemeral stack of values since an array's contents live on
the heap.
 
B

Ben Morrow

Quoth "szr said:
Isn't it more correct to say that an array holds a *list* of scalars? If
so, then it seems what I originally said is correct; an *array's*
*value* is a list, which contains scalars (numbers, strings, and refs.)

Mo, it's not. For instance, an array can be spliced, which a list
can't.

Ben
 
N

nolo contendere

Ben said:
Quoth Frank Seitz <[email protected]>: [...]
use strict;
use warnings;
my @a = qw/a b c/;
for my $v (@a) {
    push @a,'d' if $v eq 'c';
    print "$v\n";
}
Good point. for is a little weird in this respect...

Nothing really weird about it. In that case above, it's no different
than:

for (my $i=0; $i<@a; $i++) {
   my $v = $a[$i];
   push @a,'d' if $v eq 'c';
   print "$v\n";

}

In either case, it's going over the array, one element at a time, in
sequence, s oif you "push" something onto the end, it grows the array by
one and thus the for look keeps going.

I think the 'weirdness' stems from the notion that 'for' supposedly
builds up a list prior to iterating over it, as opposed to 'while'
which (with respect to filehandles at least) does not. I'm not well-
versed enough to analyze the internals of how 'for' is implemented to
understand what exactly happens if LIST is simply a list, or an array,
or part of each, or if something gets appended, prepended, spliced to
an array that is part of LIST. Based on prior threads, it appears that
the behavior varies. Since the behavior is not really consistent (and
not really documented), it can validly be labeled as 'weird'.
 
B

Ben Morrow

Quoth "szr said:
Ben said:
Good point. for is a little weird in this respect...

Nothing really weird about it. In that case above, it's no different
than:

for (my $i=0; $i<@a; $i++) {
my $v = $a[$i];
push @a,'d' if $v eq 'c';
print "$v\n";
}

It is, though. It only works if the LIST given to for is a single array:

my @ary = qw/a b c/;
for (@ary, ()) {
push @ary, 'd' if /c/;
print;
}
__END__
a
b
c

and map doesn't work like that at all

my @ary = qw/a b c/;
map {
push @ary, 'd' if /c/;
print;
} @ary;
__END__
a
b
c

and nor do sub calls. I suspect it's actually a bug: some sort of
optimization that's leaking out, and is now of course unfixable.

Ben
 
S

szr

nolo said:
Ben said:
Quoth Frank Seitz <[email protected]>: [...]

use strict;
use warnings;
my @a = qw/a b c/;
for my $v (@a) {
push @a,'d' if $v eq 'c';
print "$v\n";
}
Good point. for is a little weird in this respect...

Nothing really weird about it. In that case above, it's no different
than:

for (my $i=0; $i<@a; $i++) {
my $v = $a[$i];
push @a,'d' if $v eq 'c';
print "$v\n";

}

In either case, it's going over the array, one element at a time, in
sequence, s oif you "push" something onto the end, it grows the
array by one and thus the for look keeps going.

I think the 'weirdness' stems from the notion that 'for' supposedly
builds up a list prior to iterating over it,

Exactly. It builds a list, when necessary (like when you
use for (<FH>) { ... } ), unless it's alreayd there ( like
with for my $element (@array) { ... } ) and /THEN/ iterates over it.

It just keeps going until the list is expended. Adding to the array like
in the quoted examples above makes the list longer and hence the extra
iteration (since the length of the list is checked each time through the
loop.)
 
S

szr

comp.llang.perl.moderated said:
A purely semantic case can be made that an array contains a list.
However, internally Perl's "list" as discussed in this thread is just
a stack where values are stored/retrieved for the very limited
lifetime of a particular statement.
So I think it'd mis-charactrize an array to say it holds a list in the
sense of a ephemeral stack of values since an array's contents live on
the heap.

Well, yes and no. If you want to talk about the internal inner workings,
yes it all lives on the heap somewhere.

However, at the surface, an array's *literal* value is a List, is it
not, just as a scalar's literal values can be 123 & "abc" ?
 
N

nolo contendere

nolo said:
Ben Morrow wrote:
Quoth Frank Seitz <[email protected]>:
[...]
use strict;
use warnings;
my @a = qw/a b c/;
for my $v (@a) {
push @a,'d' if $v eq 'c';
print "$v\n";
}
Good point. for is a little weird in this respect...
Nothing really weird about it. In that case above, it's no different
than:
for (my $i=0; $i<@a; $i++) {
my $v = $a[$i];
push @a,'d' if $v eq 'c';
print "$v\n";
}
In either case, it's going over the array, one element at a time, in
sequence, s oif you "push" something onto the end, it grows the
array by one and thus the for look keeps going.
I think the 'weirdness' stems from the notion that 'for' supposedly
builds up a list prior to iterating over it,

Exactly. It builds a list, when necessary (like when you
use   for (<FH>) { ... }   ), unless it's alreayd there ( like
with   for my $element (@array) { ... }   ) and /THEN/ iterates over it.

It just keeps going until the list is expended. Adding to the array like
in the quoted examples above makes the list longer and hence the extra
iteration (since the length of the list is checked each time through the
loop.)

Provably untrue. See Ben's example. I'll restate the concept below.

my @ary = qw/a b c/;
# for (@ary, ()) {
# for ( (), @ary ) {
for ( @ary ) {
push @ary, 'd' if /c/;
print;
}

...

only the uncommented 'for' line prints a 'd' at the end. so what you
say MAY be true if LIST is ONLY an array.
 
X

xhoster

szr said:
Exactly. It builds a list, when necessary (like when you
use for (<FH>) { ... } ),

I would argue that it is not *necessary* to do that. It *could* be
special-cased to read from <FH> one line at a time rather than building
a list at the beginning, rather like the special cases that exist for
a single array, or a simple range (1..1e6). Of course, then the docs would
have to add a "so don't do that" warning on doing insane things like
reading from the file handle in side the loop or changing $/.


Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
B

Ben Bullock

No. This reads the contents of the file into a list, and then assigns
that list to an array. The contents of the array are no longer anything
to do with the file.

I'm not sure what sense you're using the word "read" here but it isn't
the usual one.
If I read a book, the words go into my head, but after that if I burn
the book, then usually my head doesn't catch fire, and if I shoot
myself in the head, then the book doesn't get a bullet hole through
it.

Similarly, in my understanding of the word "read" for computers, if I
read a file into an array, I don't expect that deleting or altering
the array after the "read" statement has finished will affect the
file, and vice-versa.
 
S

szr

nolo said:
nolo said:
Ben Morrow wrote:
Quoth Frank Seitz <[email protected]>:
[...]
use strict;
use warnings;
my @a = qw/a b c/;
for my $v (@a) {
push @a,'d' if $v eq 'c';
print "$v\n";
}
Good point. for is a little weird in this respect...
Nothing really weird about it. In that case above, it's no
different than:
for (my $i=0; $i<@a; $i++) {
my $v = $a[$i];
push @a,'d' if $v eq 'c';
print "$v\n";

In either case, it's going over the array, one element at a time,
in sequence, s oif you "push" something onto the end, it grows the
array by one and thus the for look keeps going.
I think the 'weirdness' stems from the notion that 'for' supposedly
builds up a list prior to iterating over it,

Exactly. It builds a list, when necessary (like when you
use for (<FH>) { ... } ), unless it's alreayd there ( like
with for my $element (@array) { ... } ) and /THEN/ iterates over it.

It just keeps going until the list is expended. Adding to the array
like in the quoted examples above makes the list longer and hence
the extra iteration (since the length of the list is checked each
time through the loop.)

Provably untrue. See Ben's example. I'll restate the concept below.

my @ary = qw/a b c/;
# for (@ary, ()) {
# for ( (), @ary ) {
for ( @ary ) {
push @ary, 'd' if /c/;
print;
}

...

only the uncommented 'for' line prints a 'd' at the end. so what you
say MAY be true if LIST is ONLY an array.

Isn't that because the two commented one are two lists being combined
into a new list, and it's *that* new list that's being iterated over, so
even if you add to @ary, it doesn't change the "new list", which is just
that, a new list created at the start of the loop before iterating
begins - therefore the values of the new list are set and @ary has
nothing to do with it after the create of the "new list."

Isn't this correct?
 
P

Peter J. Holzer

Isn't that because the two commented one are two lists being combined
into a new list, and it's *that* new list that's being iterated over, so
even if you add to @ary, it doesn't change the "new list", which is just
that, a new list created at the start of the loop before iterating
begins - therefore the values of the new list are set and @ary has
nothing to do with it after the create of the "new list."

Yes. But the same should be true for

for (@ary) {
...
}

for() expects a list, the list is constructed from the elements of @ary.
If you modify @ary after the list is constructed, the list shouldn't be
affected, but it is. I think Ben Morrow is right here: This smells like
an optimization: If there is only a single array, it can be used
directly instead of creating a list from it.

hp
 
P

Peter J. Holzer

I'm not sure what sense you're using the word "read" here but it isn't
the usual one.
If I read a book, the words go into my head, but after that if I burn
the book, then usually my head doesn't catch fire, and if I shoot
myself in the head, then the book doesn't get a bullet hole through
it.

Similarly, in my understanding of the word "read" for computers, if I
read a file into an array, I don't expect that deleting or altering
the array after the "read" statement has finished will affect the
file, and vice-versa.

I think Ben Morrow used the word "read" exactly in the sense you
described here.

What he was getting at is that

consists (at least conceptually) of two distinct operations:

First, the <> operator is called on handle. This reads lines from handle
and returns a list with one line per element.

Then the = operator is called which takes the list from the previous
step and assigns each element to an element of the array @ary, shrinking
or expanding @ary as needed.

The <> operator doesn't know or care what happens to the list it returns
and the = operator doesn't know or care where the list that it takes
comes from. So while the overall effect of that line is "to read a file
into an array", there is no operation which does that.

hp
 
S

szr

Peter said:
Yes. But the same should be true for

for (@ary) {
...
}

for() expects a list, the list is constructed from the elements of
@ary. If you modify @ary after the list is constructed, the list
shouldn't be affected, but it is. I think Ben Morrow is right here:
This smells like an optimization: If there is only a single array, it
can be used directly instead of creating a list from it.

Actually the behaviors of "for (@ary)" and "for (@ary, ())" do seem
consistant if you really think about it. The resulting list is what it
iterates over (from the first element, to what ever *count* is... in the
former case *count* come fro mthe array, and since the condition is
checked at the start of each iteration, if the array is added to, the
count is incremented.

In the latter case, a new list is created from contents of @ary + an
empty list, which gives you a new list, which contains the values of
@ary, but is a new seperate list, and thus is not effected by changes to
@ary because it has it's own copy of @ary's values.
 
B

Ben Morrow

Quoth "szr said:
Actually the behaviors of "for (@ary)" and "for (@ary, ())" do seem
consistant if you really think about it. The resulting list is what it
iterates over (from the first element, to what ever *count* is... in the
former case *count* come fro mthe array, and since the condition is
checked at the start of each iteration, if the array is added to, the
count is incremented.

In the latter case, a new list is created from contents of @ary + an
empty list, which gives you a new list, which contains the values of
@ary, but is a new seperate list, and thus is not effected by changes to
@ary because it has it's own copy of @ary's values.

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
 
N

nolo contendere

Actually the behaviors of "for (@ary)" and "for (@ary, ())" do seem
consistant if you really think about it. The resulting list is what it
iterates over (from the first element, to what ever *count* is... in the
former case *count* come fro mthe array, and since the condition is
checked at the start of each iteration, if the array is added to, the
count is incremented.

In the latter case, a new list is created from contents of @ary + an
empty list, which gives you a new list, which contains the values of
@ary, but is a new seperate list, and thus is not effected by changes to
@ary because it has it's own copy of @ary's values.

Is this explanation based on analysis of the source implementation? or
are you just using inductive reasoning to extrapolate a general rule
from a few test cases?
 

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
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top