References to an array in a foreach

D

David K. Wall

David Green said:
I have a problem with references to arrays and would be grateful
if someone could give me some help or alternatively propose a
better method to use in solving my problem.

Take for example the following code:

my @animals = ( "\@reptiles", "\@mammals", "\@birds" );

@animals now contains the strings '@reptiles', '@mammals', and
'@birds', but no references.
my @birds = ( "owl", "swan", "pelican" );
my @reptiles = ( "crocodile", "gecko" );
my @mammals = ( "fox", "cheeta", "man" );

It's probably a good thing that @animals only contains strings,
because the arrays you meant to reference didn't exist yet.
What I think I've done here is set up an array called @animals
which contains references to the three arrays @birds, @reptiles
and @mammals.

Nope, sorry.

What I would like to do is use a pair of <foreach> loops to read
each value from the three arrays in sequence (exact order
unimportant).

I'd suggest reading perllol.

Defining two worker variables:
my $thiskey, $thatkey;

foreach $thatkey (@animals) {

foreach $thiskey (@$thatkey) { # Here I try to dereference
the array print $thiskey . ","; # and presumably
fail?
};
};

I would expect the output:
"crocodile,gecko,fox,cheeta,man,owl,swan,pelican", but instead get
no output. To even get this code to run I have to remove <use
strict> else Perl refuses to run the code.

Don't do that. Perl knows more about it than you do at the moment.
:)

I'm not the best explainer (or at least I'm too lazy to type a lot of
stuff), so how about trying this:

use strict;
use warnings;

my @birds = qw(owl swan pelican);
my @reptiles = qw(crocodile gecko);
my @mammals = qw(fox cheeta man);

my @animals = \( @reptiles, @mammals, @birds );

print join ', ', map { @$_ } @animals;
 
D

David Green

Hey all,

I have a problem with references to arrays and would be grateful if
someone could give me some help or alternatively propose a better method
to use in solving my problem.

Take for example the following code:

my @animals = ( "\@reptiles", "\@mammals", "\@birds" );
my @birds = ( "owl", "swan", "pelican" );
my @reptiles = ( "crocodile", "gecko" );
my @mammals = ( "fox", "cheeta", "man" );

What I think I've done here is set up an array called @animals which
contains references to the three arrays @birds, @reptiles and @mammals.

What I would like to do is use a pair of <foreach> loops to read each
value from the three arrays in sequence (exact order unimportant).

Defining two worker variables:
my $thiskey, $thatkey;

foreach $thatkey (@animals) {

foreach $thiskey (@$thatkey) { # Here I try to dereference the array
print $thiskey . ","; # and presumably fail?
};
};

I would expect the output:
"crocodile,gecko,fox,cheeta,man,owl,swan,pelican", but instead get no
output. To even get this code to run I have to remove <use strict> else
Perl refuses to run the code.

The ultimate aim in this seemingly strange setup is to allow an unlimited
number of members to @animals and an unlimited number of animals in each
different 'kingdom'. In reality i'm actually using such a system to manage
a lot of metadata for a package manager I'm working on.

How can I get the output I'm after (preferably retaining strict refs) or
alternatively provide data organised in such a way. If any more
information helps or I'm unclear please let me know,

Thanks,
Dave
 
A

A. Sinan Unur

Hey all,

I have a problem with references to arrays and would be grateful if
someone could give me some help or alternatively propose a better
method to use in solving my problem.

Take for example the following code:

my @animals = ( "\@reptiles", "\@mammals", "\@birds" );
my @birds = ( "owl", "swan", "pelican" );
my @reptiles = ( "crocodile", "gecko" );
my @mammals = ( "fox", "cheeta", "man" );

What I think I've done here is set up an array called @animals which
contains references to the three arrays @birds, @reptiles and
@mammals.

That is absolutely one hundred percent wrong. Where have you every seen
such syntax? You can't make stuff up and expect it to work you know.

What you have done instead is to create an array called @animals
containing the strings '@reptiles', '@mammals', and '@birds'.
What I would like to do is use a pair of <foreach> loops to read each
value from the three arrays in sequence (exact order unimportant).

Defining two worker variables:
my $thiskey, $thatkey;

Always declare your variables in the smallest possible scope. Don't give
them misleading names (such as $key).
foreach $thatkey (@animals) {

foreach $thiskey (@$thatkey) { # Here I try to dereference the
array print $thiskey . ","; # and presumably fail?

I am speechless.

You can't make stuff up like this.
I would expect the output:
"crocodile,gecko,fox,cheeta,man,owl,swan,pelican", but instead get no
output.

Why would you expect that?
To even get this code to run I have to remove <use strict>
else Perl refuses to run the code.

It is a BAD SIGN when you have to remove use strict to get your code to
run. Why don't you instead read the message you get? WHile you are at it,
you could also add a simple use diagnostics to get a more detailed
description.
The ultimate aim in this seemingly strange setup is to allow an
unlimited number of members to @animals and an unlimited number of
animals in each different 'kingdom'. In reality i'm actually using
such a system to manage a lot of metadata for a package manager I'm
working on.

Please let us know what it is so we know never ever under any
circumstances to use it.
If any more information helps or I'm unclear please let me know,

You are very clear. You refuse to read.

Have you looked at perldoc perlref?

Sinan.
 
B

Brian McCauley

David said:
Hey all,

I have a problem with references to arrays and would be grateful if
someone could give me some help or alternatively propose a better method
to use in solving my problem.

Take for example the following code:

my @animals = ( "\@reptiles", "\@mammals", "\@birds" );
my @birds = ( "owl", "swan", "pelican" );
my @reptiles = ( "crocodile", "gecko" );
my @mammals = ( "fox", "cheeta", "man" );

What I think I've done here is set up an array called @animals which
contains references to the three arrays @birds, @reptiles and @mammals.

No you have not. @animals is an array of strinf. If you want it to be
an array of references you'd need to remove the quotes from the first line.
What I would like to do is use a pair of <foreach> loops to read each
value from the three arrays in sequence (exact order unimportant).

Defining two worker variables:
my $thiskey, $thatkey;

Firstly you mean "declaring" not "defining". Secondly you are suffering
from the unfortuante affliction of "premature declaration". You should
always declare all variables in the smallest applicable scope unless you
have a positive reason to do otherwise. In the case of for-loop
iterator variables the correct place to delare these variables is in the
for statement itself.
foreach $thatkey (@animals) {

foreach $thiskey (@$thatkey) { # Here I try to dereference the array
print $thiskey . ","; # and presumably fail?
};
};

If @animals where an array of array references that code would would
work just fine.
I would expect the output:
"crocodile,gecko,fox,cheeta,man,owl,swan,pelican", but instead get no
output. To even get this code to run I have to remove <use strict> else
Perl refuses to run the code.

If your smoke alarm is sounding, put out the fire, do not remove the
batteries. Did you actually read the error Perl gave you? It told you
what was wrong. It told you that you were using a string where you
needed a reference.
 
T

Todd de Gruyl

my @animals = ( "\@reptiles", "\@mammals", "\@birds" );

Two problems:
The format "\@array" gives you the same thing as '@array', in other
words, a literal ampersand. What you probably meant to do is:

my @animals = ( \@reptiles, \@mammals, \@birds );

The second problem here is that you are referencing arrays that don't
exist yet. If you had started out with:

use warnings;
use strict;

then Perl would have told you some of the problems (once you fixed the
problem with the quotes, anyway).
my $thiskey, $thatkey;

This should probably be:

my ($thiskey, $thatkey); # [1]

or better yet, move the my into the foreach statements:

foreach my $thatkey (@animals) {
foreach my $thiskey (@$thatkey) {
print $thiskey . ",";
};
};


### Here it is with the errors fixed:

use warnings;
use strict;

my @birds = ( "owl", "swan", "pelican" );
my @reptiles = ( "crocodile", "gecko" );
my @mammals = ( "fox", "cheeta", "man" );
my @animals = ( \@reptiles, \@mammals, \@birds );

foreach my $thatkey (@animals) {
foreach my $thiskey (@$thatkey) {
print $thiskey . ",";
};
};

###

[1] from perldoc -f my: If more than one value is listed, the list must
be placed in parentheses.
 
A

A. Sinan Unur

I am speechless.

You can't make stuff up like this.

I sincerely apologize for this remark. I do not know where the word 'array'
came from in my copy. Must have been some kind of inadvertent paste on my
part.

To make up for my mistake, here is an answer to your other question:
The ultimate aim in this seemingly strange setup is to allow an
unlimited number of members to @animals and an unlimited number of
animals in each different 'kingdom'. In reality i'm actually using
such a system to manage a lot of metadata for a package manager I'm
working on.

What you really want to use is a hash for animals, rather than an array. It
will make your life easier.

That is:

#! perl

use strict;
use warnings;

my %animals = (
birds => [ qw(owl swan pelican) ],
reptiles => [ qw(crocodile gecko) ],
mammals => [ qw(fox cheeta man) ],
);

# add a species to a group

push @{ $animals{birds} }, 'sparrow';

for my $species (keys %animals) {
print ucfirst $species, ": ";
print join(', ', @{ $animals{$species} }), "\n";
}

__END__

Hope this helps.

Sinan.
 
A

A. Sinan Unur

Yes and yes. Notice how others were kind enough to provide a bit of a
description as to where to look. It's fine to tell people to RTFM if
you tell them which manual you would like them to read - I have at
least a thousand pages of documentation packaged with my installation
to read, let alone other resources.

I did tell you exactly where to look.

perlref, that is, "Perl references and nested data structures", ought to be
the first place you look at when you are trying to figure out how to take a
reference to something.

Oh, by the way, perldoc perltoc will give you a table of contents so you
don't have to guess.

Sinan.
 
D

David Green

That is absolutely one hundred percent wrong. Where have you every seen
such syntax? You can't make stuff up and expect it to work you know.
It's an adaptation (errors my own) of some code I found online. I hope
that by trialing new ideas I might improve my coding skills. Is that not
how most things, especially new languages are learnt?
Always declare your variables in the smallest possible scope. Don't give
them misleading names (such as $key).

Provided as an illustration only, but even so I would question as a
general idea in programming that the problem of having such a named
variable that's going to fall out of scope *very* soon and only iterate
over a set of values is not terribly significant.
It is a BAD SIGN when you have to remove use strict to get your code to
run. Why don't you instead read the message you get?

I did read it (somewhat obviously) and whilst I understood something was
wrong and to some extent why I did not have the knowledge to fix it. Of
course it's a bad sign - why did I run with use strict to start with? It's
an observation that it works without- read my post and you'll see how I
want to run without having to remove it!
You are very clear. You refuse to read.

Have you looked at perldoc perlref?
Yes and yes. Notice how others were kind enough to provide a bit of a
description as to where to look. It's fine to tell people to RTFM if you
tell them which manual you would like them to read - I have at least a
thousand pages of documentation packaged with my installation to read, let
alone other resources.

I would be interested in your replies but please some actual content this
time rather than a series of insults and rebuttal that offers no
assistance, such posts are a rather a waste of everyones bandwidth.

David
 
D

David Green

### Here it is with the errors fixed:

use warnings;
use strict;

my @birds = ( "owl", "swan", "pelican" );
<snip>
Thanks kindly for your help, I'll try this code as well as the
perllol documentation recommended earlier. I think I dropped the
parentheses in a hurry typing - didn't want to copy and paste a lot of
of superfluos code so typed out fresh what I had in mind, appologies.

Regards,
Dave
 
A

A. Sinan Unur

Looks like it came from word-wrap to me.

Once again, you are right.

Comments in the right margin do have a tendency to wrap around. One ought
to be able to copy and paste the posted code without too much effort. The
commenting style above does not help with that.

Sinan.
 
E

Eric Bohlman

Really, this sounds like something the SPCA might come after you for...
:)

I could see them objecting to a hash *of* animals, but what would worry
them about a hash *for* animals? :)
 

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,770
Messages
2,569,584
Members
45,077
Latest member
SangMoor21

Latest Threads

Top