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

Hi-dilly ho-dilly, Monkerinos...

Say I were to tie a hash to something...

tie(%hash, 'My::Hash::Tie::Class', @args);

With 'tied', I can get at the underlying stored object:

my $obj = tied(%hash);

What I want to do is sort of the inverse of tied -- given an underlying object that is an instance of My::Hash::Tie::Class, I want to be able to recreate a tied hash:

my %newhash = Foo($obj);

And now %newhash is a tied hash to My::Hash::Tie::Class... though I'm not sure if it would be a copy-by-ref or a copy-by-value of the original %hash. (Not much sure if it makes a difference to met yet, either.)

Any suggestions on what Foo() should be? Either how to create it myself, or what real function / CPAN module / etc. exists out there already? Note that I'm not just looking for functions. Whatever method does the job, I'm happy with.

Cheers,
Richard

Replies are listed 'Best First'.
Re: Given a tie object, get a tied hash (or scalar, or whatever)
by broquaint (Abbot) on Aug 13, 2003 at 15:39 UTC
    This can't really be done at a totally generic level as the object is really just the implementation of the given tie interface and doesn't have the tie magic. Probably your best bet is to create a method in the given tie class implementation that recreates the tied variable e.g
    { package Tie::Hash::Foo; use Tie::Hash; @ISA = 'Tie::StdHash'; sub recreate { tie my %tmp, __PACKAGE__; %tmp = %{$_[0]}; return \%tmp; } } use Data::Dumper; my $obj; { $obj = tie(my %hash, 'Tie::Hash::Foo'); %hash = qw/foo bar/; } my $hash = $obj->recreate; print "%\$hash is tied\n" if tied(%$hash); print Dumper($hash); __output__ %$hash is tied $VAR1 = { 'foo' => 'bar' };
    That's a rather hackish solution, but it should give you some idea of what to do.
    HTH

    _________
    broquaint

Re: Given a tie object, get a tied hash (or scalar, or whatever)
by adrianh (Chancellor) on Aug 13, 2003 at 15:18 UTC

    Why not alter your classes TIEHASH to take an optional object-to-use argument so you could then do:

    tie(%newhash, 'My::Hash::Tie::Class', using => $obj, @args);

    Sound sane?

      Hmm... it's an idea. But really, I'm not going to be using My::Hash::Tie::Class. I'll be working with Apache::Session or Apache::SessionX. (That was meant to be a metasyntactic class name variable.)

      I could end up subclassing either to My::ApacheSessionRipOff and implement things this way I suppose, but hopefully that will be my second option on how to proceed, and not my only one.

      Cheers,
      Richard

        Can you explain what you're trying to do with Apache::Session? There might be another way.
        But really, I'm not going to be using My::Hash::Tie::Class. I'll be working with Apache::Session or Apache::SessionX. (That was meant to be a metasyntactic class name variable.)

        Ah. In that case something like this will probably do the trick (untested code):

        package Tie::WrapUsing; sub TIEHASH { my ($class, $object) = @_; return $object; }; package main; use Test::More tests => 2; use Apache::Session::File; my $object = tie my %orig, 'Apache::Session::File', undef, { Directory => '/tmp' }; tie my %dupe, 'Tie::WrapUsing', $object; $orig{foo}=42; $dupe{bar}=24; is $dupe{foo}, 42, 'change in original reflected in duplicate'; is $orig{bar}, 24, 'change in duplicate reflected in original';

        However, your real problem seems to be that you want to use a tied hash as an object - which kind of defeats the purpose :-) If I were you I'd use an object-based session system like Cache::Cache instead.

Re: Given a tie object, get a tied hash (or scalar, or whatever)
by bean (Monk) on Aug 13, 2003 at 15:32 UTC
    Hmm. I don't see how this would work for Tie::Persistent, the tie package I'm most familiar with, and I'm sure other tie packages would have similar problems. In Tie::Persistent, the variable is dumped (on destruction and as requested) to a file (specified when tied) - your new variable would compete for access to the file and one would clobber the other. Maybe if you did it like this:
    my %newhash = Foo($obj, @newargs);
    But that would probably be equivalent to just tie-ing the new hash with the new args and recursively copying the old hash to the new one.
    Update:
    Actually, the recursive copying is problematic as well because it may have side effects...
Re: Given a tie object, get a tied hash (or scalar, or whatever)
by wirrwarr (Monk) on Aug 13, 2003 at 16:07 UTC
    Why do you have to use $obj in the call to Foo()? Shouldn't you simply use the %hash value to create %newhash?
    The basic problem that I see is that $obj doesn't know anything about the class %hash was tied to, so there is no simple way to implement Foo($obj).
      > The basic problem that I see is that $obj doesn't know anything about the class %hash was tied to

      No? What would ref($obj) return? Remember that $obj comes from

      my $obj = tied(%hash);

      And the very def'n of tied is that it returns the underlying object that implements the tied thingy.

      Cheers,
      Richard