![]() |
|
|
| Subject:
Perl Array References
Category: Computers > Programming Asked by: lexi-ga List Price: $20.00 |
Posted:
16 Sep 2004 15:19 PDT
Expires: 16 Oct 2004 15:19 PDT Question ID: 402228 |
This is an obscure perl question, not for the faint of heart.
Suppose you have a hash. In that hash is some key "foo". The value
of "foo" in the hash might be either a scalar or an array. (Assume it
is not possible to modify the creation of the hash to make "foo"
always be an array.)
Example:
my %hash;
$hash{"foo"} = "one"; // it's a scalar here
$hash{"foo"} = [ "two", "three"]; // it's an array here
Is it possible to dereference $hash{"foo"} in such a way that the
result is always an array? That is, for the second example, I want to
get back the array as-is, but for the first example, I want perl to
wrap "one" as an array of one element. In other circumstances (i.e.
not when dereferencing a hash element) this is easy, because you can
just sort of evaluate a scalar in a list context and get a one-element
array.
So the first thing I tried was using an explicit cast to list
context:
my @foos = @{$hash{"foo"}};
This works for the second example but not for the first, because perl
knows that "one" is not an array reference.
Then I tried an implicit cast:
my @foos = $hash{"$foo"};
This works for the first example (creating the one-element array) but
not the second, because the hash element is "really" an array ref, so
@foos becomes a one-element array whose member is a reference to the
array of interest.
Some experimenting did yield a solution:
my @foos = cast_to_array($hash{"foo"});
sub cast_to_array {
my ($x) = @_;
ref($x) eq "ARRAY" ? @$x : ( $x );
}
But I have this itchy feeling that there is More Than One Way To Do
It, and that one of those other ways must be better.
So the question is: what is a one-line construction for dereferencing
this hash element to yield an array, regardless of whether the hash
value is really a scalar or an array? |
|
| There is no answer at this time. |
|
| Subject:
Re: Perl Array References
From: hdp-ga on 30 Sep 2004 20:30 PDT |
It is worth noting that the hash value is *always* a scalar. You mean
to distinguish between scalars that are not references and scalars
that are array references. I know this may seem nitpicky, but it's
important.
The easiest way to do what you want is to do what you've done; use a
wrapper function.
The slightly more complex way is to read the hash only through a
closure. For example:
my %hash;
sub hash_get {
my $key = shift;
sub whatever {
my $data = shift;
$data ? ref($data) eq "ARRAY" ? @$data : [$data] : []
}
You could also use a tied hash that stored everything as an arrayref.
perldoc perltie, and its STORE would be something like
sub STORE {
my ($self, $key, $val) = @_;
$self->{$key} = (ref($val) eq "ARRAY" ? $val : [$val]);
}
its FETCH would be something like
sub FETCH {
my ($self, $key) = @_;
return @{$self->{$key} || []};
} |
| Subject:
Re: Perl Array References
From: hdp-ga on 30 Sep 2004 20:32 PDT |
Ooops. Hit "post" in the middle of typing (emacs reflexes getting in
the way). hash_get should be:
sub hash_get {
my $key = shift;
return () unless exists $hash{$key};
my $val = $hash{$key};
return ref($val) eq "ARRAY" ? @$val : $val
}
The "sub whatever" can be ignored. |
If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you. |
| Search Google Answers for |
| Google Home - Answers FAQ - Terms of Service - Privacy Policy |