kindergarten array vs. for question

D

Dan Jacobson

my @a=(1,2,3); my @b=(4,5,6);
for((((@a))),(((@b)))){ #What do I have to do to this line to make
print "new array\n"; #this line get printed only twice, not six times?
for($_){
print "element $_\n"}}
 
E

Eric Schwartz

Dan Jacobson said:
my @a=(1,2,3); my @b=(4,5,6);
for((((@a))),(((@b)))){ #What do I have to do to this line to make

Yikes! You need a quick trip to 'perldoc perldata'. Do not pass go,
do not collect $200. I'm not trying to make you feel bad here, but
this is very basic stuff. If you didn't read this in perldata, you
probably need to sit down and read that manpage, and probably at least
skim perltoc as well.

A short excerpt from perldata:

LISTs do automatic interpolation of sublists. That is, when a
LIST is evaluated, each element of the list is evaluated in
list context, and the resulting list value is interpolated into
LIST just as if each individual element were a member of LIST.

So, what you're iterating over is the list (((@a))),(((@b))), which is
equivalent to (@a),(@b), which is equivalent to @a,@b, which is in
turn reduced to a list containing all the elements of @a followed by
all the elements of @b.

As a stylistic aside, if I ever find myself using $_ explicitly in a
loop, that's usually a sign to me that I need to be using an explicit
name for the variable. In your case, I might write it:

for my $element (@a,@b) {
....
}

And then use $element where you have $_. This won't work in EVERY
case, but it does work 9 times out of 10.
print "new array\n"; #this line get printed only twice, not six times?
for($_){
print "element $_\n"}}

Also, this is kinda ugly from a personal POV: it doesn't match any
standard indenting style I'm familiar with, and it makes it harder to
find the close bracket for the outer for by hiding it at the end of
the inner for. And even that one might be missed on a cursory
reading.

Anyway, to answer your question, the "right" answer depends on why you
want to know. If you want to count how many arrays you put in the top
of the for loop, well, that's a bit odd, since you're specifying them
explicitly. You probably want to iterate over references to the
arrays, except then you lose the name of the array when you do so (not
sure if that would be a problem or not).

That might look like:

for my $array_ref (\@a, \@b) {
print "new array, ref value: [$ref]";
}

read perlretoot for more info on references in Perl. Also perlref.

-=Eric
 
A

Andrew Hamm

Dan said:
my @a=(1,2,3); my @b=(4,5,6);
for((((@a))),(((@b)))){
#What do I have to do to this line to make
#this line get printed only twice, not six times?
print "new array\n";
for($_){
print "element $_\n"
}
}

I see what you are trying to achieve (I think) and you will need to use
references. The answer will be more complicated than you might expect!

my @a = (1, 2, 3);
my @b = (4, 5, 6);

for(\@a, \@b) {
print "new array\n";
for(@$_) {
print " element $_\n";
}
}

No matter how many ( ) you wrap around a list, it is flattened down to a
single-level list in Perl. So your attempt to make

(((@a))),(((@b)))

is the same as

@a, @b

Which is given to "for"; and guess what, "for" takes a list which is
logically (and syntactically) wrapped in another ( ) so you get

(@a, @b)

which ultimately yields

(1, 2, 3, 4, 5, 6)

my solution takes the "address of" @a and @b by applying the \ operator.
NOTE: Perl is higherlevel than a machine-oriented language like C or C++,
so calling it an "address of" is not strictly true. There is more in a
Perl "reference" than just a simple address. But for practical purposes
it's very simple to informally consider it to be an address if that helps
you to understand.

Now, my outside for loop gets two values: the address of @a and the
address of @b. This gives you the two prints of the line you want.

The next problem is getting to the values "pointed to" or referred to by
the reference. If $X contains a reference, then "pretend" or treat it as a
unit which is a variable name:

$thingy # a scalar variable
@listy # an array variable
$$rthingy # dereference a reference to a scalar variable
@$rlisty # dereference a reference to an array variable

for total safety while you are learning, it's safer to write

${$rthingy} @{$rlisty}

because the { } puts a very clear boundary around the reference, and
really makes it clear what goes with what.

There's no point in me going any further here because the subject is
wellcovered in the doco. See

perldoc perlreftut

and

perldoc perlref

and study well. References are very powerful, a bit mind-bending, and are
central to the Perl way of making complex data structures.
 

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,269
Messages
2,571,097
Members
48,773
Latest member
Kaybee

Latest Threads

Top