Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things


by Cine (Friar)
on Aug 19, 2001 at 16:50 UTC ( #106017=perlquestion: print w/replies, xml ) Need Help??
Cine has asked for the wisdom of the Perl Monks concerning the following question:

How do I alter a to behave like b, while keeping my %c?
That is how to make the final line print ab while using the construct $c{a} = 'a' somehow in a.
sub a { my $ref = shift; my %c = %$ref; $c{a} = 'a'; } sub b { my $c = shift; $$c{b} = 'b'; } my %c; &a(\%c); &b(\%c); print foreach (keys %c);

Replies are listed 'Best First'.
Re (tilly) 1: References
by tilly (Archbishop) on Aug 19, 2001 at 16:58 UTC
    Personally I would suggest learning to live with the syntax rather than fighting it. But there are 2 solutions:
    # Abuse the symbol table. This does not work under strict. sub a1 { local *c = shift; $c{a} = 'a'; } # Copy the hash by force. Very inefficient. sub a2 { my $ref = shift; my %c = %$ref; $c{a} = 'a'; %$ref = %c; }
    However personally I would use the following solution instead as the best mix of safe, efficient, and readable programming with references:
    # "Arrow" notation. sub a3 { my $ref = shift; $ref->{a} = 'a'; } # Or compactly sub a4 { (shift)->{a} = 'a'; }
      sub a1 { local *c = shift; $c{a} = 'a'; }
      Is almost what I want, but it will not work under strict, as you point out.
      I have however come up with two sollutions based on the same idea...
      sub f { use vars qw(%d); local *d = shift; $d{f}='f'; }
      However this will declare %d globally, which is not what I want. so:
      sub f { our %d; local *d = shift; $d{f}='f'; }
      But since I dont know how our works, I dont know how this works... Can someone explain?
        Our is a Perl 5.6 feature that gives lexically scoped access to a global variable. I dislike it for a number of reasons that are neither here nor there, but it should work from Perl 5.6.0 onwards.

        However for several reasons, not the least of which is that some day someone else will have to figure out your code and you will need to understand yet another person's, I strongly recommend getting used to the arrow syntax for dereferencing rather than playing games with the symbol table.

Re: References
by japhy (Canon) on Aug 19, 2001 at 16:55 UTC
    You can include a reassignment to %$ref at the end of the function:
    %$ref = %c;
    Or you can use a local variable and create an alias:
    use vars '%c'; # if strict is on, which it IS, RIGHT? *c = $ref;
    Now, %c is really an alias to %$ref, so changes to one will show in the other.

    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: References
by cLive ;-) (Prior) on Aug 19, 2001 at 23:35 UTC
    You can also amend %c direct:
    sub a { ${$_[0]}{a} = 'a'; }
    but I'm not really sure what your question is asking :)

    cLive ;-)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://106017]
Approved by root
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2018-01-21 07:46 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (227 votes). Check out past polls.