Re: How to untie oneself?
by tilly (Archbishop) on Jul 10, 2003 at 21:16 UTC
|
Unless you want to mess around with the internals, I don't see how this is possible.
However it is possible to achieve the same effect by having your tie method accept an optional reference which will have the value stored, and then export utility methods that use it. So you might wind up with something like this interface:
promise(\ my $result_of_long_compute, sub {
# Long computation here
});
and then you implement this along the following lines:
sub promise {
my ($to_tie, $implement, $opts);
if (UNIVERSAL::isa($to_tie, 'SCALAR')) {
tie $$to_tie, Data::Lazy, $implement, $opts;
}
elsif (UNIVERSAL::isa($to_tie, 'HASH')) {
...
}
And then document that using the promise() utility function is faster than using the tie interface. | [reply] [d/l] [select] |
|
|
---------testUntie.pl---------
#!perl
use Data::Lazy;
print "ref=" . \$x . "\n";
tie $x, 'Data::Lazy', sub {sleep 1; 2};
tied($x)->{'var'} = \$x;
print "Tied: " . tied($x) . "\n";
print "\$x=$x\n";
print "Tied: " . tied($x) . "\n";
print "\$x=$x\n";
---------Data/Lazy.pm---------
package Data::Lazy;
#...
sub TIESCALAR {
my $pack = shift;
my $self = {};
$self->{code} = shift;
$self->{'store'} = $_[0] if $_[0];
$self->{'type'} = 0;
# $self->{'var'} = $_[1] if $_[1];
bless $self => $pack; # That's it? Yup!
}
#...
sub FETCH {
my $self = shift;
if ($self->{'type'} == 0) { # scalar
return $self->{value} if exists $self->{value};
if (ref $self->{code} eq 'CODE') {
$self->{value} = &{$self->{code}};
} else {
$self->{value} = eval $self->{code};
}
if ($self->{'store'} == LAZY_STOREVALUE and exists $self->{'var'})
+{
my $var = $self->{'var'};
print "Try to untie $var tied to " . tied($$var) . "\n";
untie($$var);
$$var = $self->{value};
undef $self;
return $$var;
} else {
$self->{value};
}
} # ... elsif array and hash
}
#...
1;
and it printsref=SCALAR(0x1a4587c)
Tied: Data::Lazy=HASH(0x15d55d0)
Try to untie SCALAR(0x1a4587c) tied to
$x=2
Tied: Data::Lazy=HASH(0x15d55d0)
$x=2
That is I do have a reference to the right scalar, yet it's not tied ?!?
I use Perl 5.8 (ActivePerl build 805) under Win2000serverSP4.
I also tried the same code using Perl 5.6.1 (ActivePerl build 631, same OS) and there it also did not report the reference to be tied, but did succeed to untie it: ref=SCALAR(0x1ab2cc0)
Tied: Data::Lazy=HASH(0x1abf078)
Try to untie SCALAR(0x1ab2cc0) tied to
$x=2
Tied:
$x=2
Strange.
Jenda
Always code as if the guy who ends up maintaining your code
will be a violent psychopath who knows where you live.
-- Rick Osborne
Edit by castaway: Closed small tag in signature | [reply] [d/l] [select] |
|
|
Bizarre.
I guess that this is tied to the internal implementation of tie. Which I have long thought of as a leaking bandage over a self-inflicted wound.
I guess the moral is that you shouldn't push tie very far because it isn't very robust. :-(
| [reply] |
Re: How to untie oneself?
by BrowserUk (Patriarch) on Jul 10, 2003 at 22:15 UTC
|
You don't mention what kind of variable you are tying, though you do mention scalar later in your post, so this extract from the Perl 5.8 delta pod may or may not be relavent.
Self-tying Problems
Self-tying of arrays and hashes is broken in rather deep and hard-to-fix ways. As a stop-gap measure to avoid people from getting frustrated at the mysterious results (core dumps, most often), it is forbidden for now (you will get a fatal error even from an attempt).
A change to self-tying of globs has caused them to be recursively referenced (see: Two-Phased Garbage Collection in the perlobj manpage). You will now need an explicit untie to destroy a self-tied glob. This behaviour may be fixed at a later date.
Self-tying of scalars and IO thingies works.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
| [reply] |
|
|
I don't think I know what do they mean by self-tying. In either case the only type for which the untieing I want would make sense are scalars (ok maybe FILEHANDLEs as well, but Data::Lazy doesn't support that just now, and I don't think it ever will). Anyway thanks for warning me :-)
Jenda
Always code as if the guy who ends up maintaining your code
will be a violent psychopath who knows where you live.
-- Rick Osborne
Edit by castaway: Closed small tag in signature
| [reply] |
Re: How to untie oneself?
by Juerd (Abbot) on Jul 10, 2003 at 21:16 UTC
|
The only way I know of is using symbolic references. Perl crashes if you pass tie a reference to the variable that you are tieing.
See PLP::Tie::Delay.
Juerd
# { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }
| [reply] |
|
|
| [reply] |
|
|
Strange. I thought I replied yesterday.
I thought perl -e'sub TIESCALAR { } tie $foo, main, \$foo' would crash, but it doesn't with both 5.6.1 and 5.8.0. I'm sure it (or something similar) did crash in earlier versions, because I recall having discussed it on Magnet #perl, where several wizards said is was a known problem.
Or I had a very bad nightmare. If that is the case, I wonder how PLP::Tie::Delay escaped dreamworld :)
Juerd
# { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }
| [reply] [d/l] |
|
|
Re: How to untie oneself?
by runrig (Abbot) on Jul 11, 2003 at 17:35 UTC
|
Here is what I tried. I think its similar to what you've tried above. Its odd but convienient that after untie'ing you are left with a variable that has the same value as was last returned from FETCH. (At least on my perl v5.6.1). So you don't need to pass a reference to the variable in order to set it after the untie (here it is accessed through a closure). use strict;
use warnings;
package MyTied;
sub TIESCALAR {
my ($class,$code) = @_;
bless $code, $class;
}
sub FETCH {
my $self = shift;
print "Untie\n";
$self->();
}
package main;
my $var;
tie $var, 'MyTied', sub { untie $var; 4 };
print "One\n";
print "$var\n";
print "Two\n";
print "$var\n";
print "Three\n";
print "$var\n";
OUTPUT:
One
Untie
4
Two
4
Three
4
Updated. several times. | [reply] [d/l] |
|
|
One
Untie
4
Two
Untie
4
Three
Untie
4
:-(((
I tried to untie a different variable within the sub{} and that works, but untieing the variable whose FETCH handler is being processed simply doesn't work :-(
Jenda
Always code as if the guy who ends up maintaining your code
will be a violent psychopath who knows where you live.
-- Rick Osborne
Edit by castaway: Closed small tag in signature | [reply] [d/l] |
Re: How to untie oneself?
by DrHyde (Prior) on Jul 11, 2003 at 08:36 UTC
|
I'm really not 100% clear on what it is that you want to do. However, perhaps the tied function might be useful? It gives you a reference to the underlying object. | [reply] |
|
|
No. I need to go the other way around. From the object to the tied variable :-)
Jenda
Always code as if the guy who ends up maintaining your code
will be a violent psychopath who knows where you live.
-- Rick Osborne
Edit by castaway: Closed small tag in signature
| [reply] |