I ran into this and couldn\'t find the answer. I am trying to see if it is possible to \"change\" the reference of a hash. In other words, I have a hash, and a function that ret
An experimental feature which would seemingly allow you to do exactly what you're describing has been added to Perl 5.21.5, which is a development release (see "Aliasing via reference").
Sounds like you want:
use Data::Alias;
alias %hash = $h->hashref;
or if %hash is a package variable, you can instead just do:
*hash = $h->hashref;
But either way, this should almost always be avoided; why don't you simply use the hash reference?
Yes, but…
References in perl are Scalars. What you are trying to achieve is aliasing the return value. This actually is possible, but you should not do this, since it involves messing with the symbol table. Furthermore this only works for globals (declared with our): If you assign a hashref to the glob *hash
it will assign to the symbol table entry %hash
:
#!/usr/bin/env perl
use warnings;
use strict;
sub a_hashref{{a => "one", b => "two"}}
our %hash;
*hash = a_hashref;
printf "%3s -> %s\n",$_,$hash{$_} foreach keys %hash;
This is bad style! It isn't in PBP (directly, but consider section 5.1: “non-lexicals shoudl be avoided”) and wont be reported by perlcritic
but you shouldn't pollute the package namespace for a little syntactic fanciness. Furthermore it doesn't work with lexical variables (which is what you might want to use most of the time, because they are lexically scoped, not package wide). Another problem is, that if the $h->hashref
method changes its return type, you'll suddenly assign to another table entry! (So if $h->hashref
changes its return type to an arrayref, you assign to @hash, good luck detecting that). You could circumvent that by checking if $h->hashref
really returns a hashref with 'HASH' eq ref
$h->hashref` but that would defeat the purpose.
What is the problem with just keeping the reference? If you get a reference, why don't you just store it in a scalar?
$hash = $h->hashref
To read more about the global symbol table take a look at perlmod and consider perlref for the *FOO{THING}
syntax, which sadly isn't for lvalues.
To achieve what you want, you could check out the several aliasing modules on cpan. Data::Alias or Lexical::Alias seem to fit your purpose. Also if you are interested in tie
semantics and/or don't want to use XS
modules, Tie::Alias might be worth a shoot.