throop has asked for the wisdom of the Perl Monks concerning the following question:

Brethern,
I have a function, markFail, in some old code, which is hardcoded to writes value to a hash, %problemClassProps. In my new code, I'd like to write the same data to a different hash, %MEClassProps. Both hashes are global. I naively thought the following would work.
use strict; use vars qw( %problemClassProps %MEClassProps ); sub assign_ME_problem{ my($ontCategory, $ontNumbering, $mapwd) =@_; local(%problemClassProps) = %MEClassProps; markFail($mapwd, $ontCategory, $ontNumbering); 1}
When I come back from markFail, the info is in %problemClassProps, not %MEClassProps, and I lose it when I exit the scope of assign_ME_problem. I want to (locally) alias %MEClassProps to %problemClassProps. I looked through data::alias figuring it would tell me how, but no joy. I want to leave the old code alone. What's the right way to approach this?

thanks,
throop

Replies are listed 'Best First'.
Re: Aliasing one hash to another
by imp (Priest) on Jan 30, 2007 at 22:56 UTC
    You should just fix the offending code. Modifying a global hash is a bad practice. If for some reason this is not possible then you can use a glob to alias the second hash temporarily.. but this is bad mojo and should be avoided.
    use strict; use warnings; use Data::Dumper; use vars qw( %hash1 %hash2 ); %hash1 = (a => 1); %hash2 = (b => 2); do_badness(); print "hash1: ", Dumper \%hash1; print "hash2: ", Dumper \%hash2; sub do_badness { local *hash1 = \%hash2; bad_sub(); } sub bad_sub { $hash1{c} = 3; }
Re: Aliasing one hash to another
by Roy Johnson (Monsignor) on Jan 30, 2007 at 22:54 UTC
    Aliasing is done with symbolic references globs. Try this:
    local(*problemClassProps) = \%MEClassProps;
    Update: terminology fixed.

    Caution: Contents may have been coded under pressure.
Re: Aliasing one hash to another
by Zaxo (Archbishop) on Jan 30, 2007 at 23:31 UTC

    Roy Johnson has shown you the correct way to produce the alias. It's not really a symbolic reference, but a typeglob assignment. That is admittedly a thin distinction.

    I'll show in more detail how you would use this:

    #!/usr/bin/perl use warnings; use strict; use vars qw/%MEClassProps/; use Old::Code qw/markFail/; # import the old function # . . . # time to use it, mostly your code sub assign_ME_problem{ my($ontCategory, $ontNumbering, $mapwd) =@_; local(%problemClassProps) = \%MEClassProps; markFail($mapwd, $ontCategory, $ontNumbering); 1; }
    You were on the right track, but just missed the use of a reference to alias the typeglob.

    After Compline,
    Zaxo

Re: Aliasing one hash to another
by jdporter (Paladin) on Jan 30, 2007 at 23:55 UTC

    There's a much simpler way to achieve this; though it does have a bit more overhead, it should only be significant for "large" hashes, since it involves copying all the elements.

    sub assign_ME_problem { my( $ontCategory, $ontNumbering, $mapwd ) = @_; local( %problemClassProps ) = %problemClassProps; # localize a cop +y markFail( $mapwd, $ontCategory, $ontNumbering ); %MEClassProps = %problemClassProps; # copy to your hash 1 }
    A word spoken in Mind will reach its own level, in the objective world, by its own weight
Re: Aliasing one hash to another
by xmath (Hermit) on Feb 11, 2007 at 12:16 UTC
    Data::Alias should actually work fine...

    alias local %problemClassProps = %MEClassProps;

    This has the benefit of only localizing %problemClassProps, not all of *problemClassProps like Roy's solution.