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 returns a hashref, and I want to make my hash point to the location in memory specified by this ref, instead of copying the contents of the hash it points to. The code looks something like this:
%hash = $h->hashref;
My obvious guess was that it should look like this:
\%hash = $h->hashref;
but that gives the error:
Can't modify reference constructor in scalar assignment
I tried a few other things, but nothing worked. Is what I am attempting actually possible?
Sounds like you want:
or if %hash is a package variable, you can instead just do:
But either way, this should almost always be avoided; why don't you simply use the hash reference?
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").
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
: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 useXS
modules, Tie::Alias might be worth a shoot.