Dear Monks,
I am having a bit of a problem with the following code--I am creating a tied scalar on the fly from within the FETCH method of a tied hash, and trying to return that tied scalar. I can get the tied scalar to be returned with a bit of cleverness, but then the tied scalar appears to no longer be tied. Even though ref tells me that it is a 'Tie::Scalar', but tied returns undef meaning it's not tied. For further wackiness, I can manually call $tied_scalar->FETCH on the tied scalar and it works, but just $tied_scalar does not automatically call fetch. Would anyone happen to know what is going on here and how I can keep the tied scalar from untying itself?

The general idea I'm trying to get working:
tie our %conf, 'My::Hash'; # $dir is a tied Tie::Scalar our $dir = $conf{'dir'}; print $dir, $/; # prints /home/foo for example # using tie magic, storing a value in $dir also updates # 'dir' in %conf $dir = '/somewhere/else'; $dir = $conf{'dir'}; print $dir, $/; # now prints /somewhere/else
I want %conf to be a general wrapper that can be treated like a hash, so tie seems like the way to go. I also want to fetch values from %conf, store them in scalars, and then when those scalars are changed I would like transparent changes to occur back in the tied hash. Kind of confusing, I know. But I need it this way, so lets just suspend alternative designs and look at it as a pure exercise in Perl.
package My::Hash; use base 'Tie::Hash'; our %hash = ('dir' => '/home/foo'); sub TIEHASH { return bless \%hash, __PACKAGE__; } sub STORE { my ($self, $key, $val) = @_; $self->{$key} = $val; } sub FETCH { my ($self, $key) = @_; my $val = $self->{$key}; tie my $tied_scalar, 'My::Scalar', $key, $val; return $tied_scalar; } 1; package My::Scalar; use base 'Tie::Scalar'; sub TIESCALAR { my ($self, $key, $val) = @_; return bless {'value' => $val, 'key' => $key , 'fetched' => 0 }, __PACKAGE__; } sub STORE { my $self = shift; my $newval = shift; my $key = $self->{'key'}; My::Hash::hash{$key} = $self->{'value'} = $newval; } sub FETCH { my $self = shift; # this cleverness is done so that Tie::Hash FETCH does not # call Tie::Scalar FETCH when it tries to return the tied # scalar. if ($self->{'fetched'}) { return $self->{'value'}; }else{ $self->{'fetched'} = 1; return $self; } } 1;
Now using the above code something unexpected happens:
tie our %conf, 'My::Hash'; our $dir = $conf{'dir'}; print ref $dir, $/; # prints 'My::Scalar'; print tied $dir ? 1 : 0; # prints 0 print $dir, $/; # prints 'My::Scalar=HASH(0x820f268)' print $dir->FETCH # prints '/home/foo'; # attempts to call $dir->STORE give lvalue errors # # why is $dir untied now yet I can still call tied methods # on it?

In reply to A Tied hash returning a tied scalar which becomes untied, why? by Withigo

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.