Google Answers Logo
View Question
 
Q: Perl Array References ( No Answer,   2 Comments )
Question  
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?
Answer  
There is no answer at this time.

Comments  
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.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

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 Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy