perl change ref of hash

前端 未结 3 1553
眼角桃花
眼角桃花 2021-01-25 07:13

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

相关标签:
3条回答
  • 2021-01-25 08:04

    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").

    0 讨论(0)
  • 2021-01-25 08:12

    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?

    0 讨论(0)
  • 2021-01-25 08:17

    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.

    0 讨论(0)
提交回复
热议问题