Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Accessing name of tied variable in tie constructor

by djcp3 (Initiate)
on Jul 10, 2013 at 13:09 UTC ( #1043464=perlquestion: print w/replies, xml ) Need Help??
djcp3 has asked for the wisdom of the Perl Monks concerning the following question:

I need to be able to access the name of the tied variable (as a string) within the TIEHASH, TIEARRAY, or TIESCALAR constructor. Is this possible? Something like this :
tie($myvariable, "MyObject"); package MyObject; sub TIEHASH { my ($title)=@_; #prints "$myvariable"; print get_tie_variable(); .... }

Replies are listed 'Best First'.
Re: Accessing name of tied variable in tie constructor
by tobyink (Abbot) on Jul 10, 2013 at 15:25 UTC

    As mentioned above, I don't think it's possible. The solution mentioned by Eily; to avoid people using your tie packages directly, and provide them with a wrapper sub which captures the name of the tied variable and passes it as an argument to tie is probably the best thing to do.

    Here's about as elegant as I could make it, but this solution is limited to package variables (i.e. our, not my)...

    #!/usr/bin/env perl use v5.14; package MyTie { use Attribute::Handlers; use Tie::Hash (); use base 'Tie::StdHash'; sub TIEHASH { my $class = shift; warn "Tied hash: @_!!!\n"; return $class->SUPER::TIEHASH(@_); } sub UNIVERSAL::MyTie :ATTR(HASH) { (my $name = ref $_[1] ? *{$_[1]} : $_[1]) =~ s/^\*?/%/; tie %{$_[2]}, 'MyTie', $name; } BEGIN { $INC{''} = __FILE__ }; } use MyTie; our %monkey :MyTie; my %gorilla :MyTie;
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Accessing name of tied variable in tie constructor
by Eily (Parson) on Jul 10, 2013 at 13:22 UTC

    If $myvariable is a package variable, you might find what you want by looking into the symbol table of caller. So technically you could do it, but that looks like a very bad idea.

    What you should actually do, is use the fact that tie can take more than two arguments. Any argument after the class will be forwarded to the tying method. You would just have to call:

    tie($myvariable, "MyObject", 'A name');.

    You could even make a sub that calls tie for you, after you gave it the variable name and class :

    sub mytie { ($name, $class) = @_; eval "tie $name, '$class', '$name';"; # UPG: I forgot the third para +meter }
    I'm not sure about that last one though, about tying a variable into the scope of an eval, even though I can't see why that wouldn't work.

    Upgrade: corrected the mytie example which was useless.

Re: Accessing name of tied variable in tie constructor
by daxim (Chaplain) on Jul 10, 2013 at 13:25 UTC
    No, not without the usual padwalking trickery.

    But Tie::StdHash derived have an identity number (documented as argument named this) which you can use to differentiate between tied variables, see example. I guess that's your real intention.

      Even PadWalker and Devel::Caller can't help you - TIEHASH doesn't get passed a reference to the tied variable, so there's no chance of it being able to figure out the variable's name.

      Also, the argument this in the Tie::StdHash documentation isn't an identity number; it's a blessed hashref. (It's what most OO Perl code would refer to as $self.)

      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (7)
As of 2018-02-19 18:48 GMT
Find Nodes?
    Voting Booth?
    When it is dark outside I am happiest to see ...

    Results (266 votes). Check out past polls.