in reply to Wierd Behavior With Tie

rational_icthus,
The following accomplishes what you want plus has the added benefit of allowing you to cache the values of the function.
package TieTest; sub TIESCALAR { my $class = shift @_; die "Incorrect # of arguments" if @_ % 2; my $self = bless {}, $class; $self->_init(@_); return $self; } sub FETCH { my $self = shift @_; my $work_around = sub { my $tgt = shift @_; if (exists $self->{$tgt}) { print "Fetching value from cache\n"; return $self->{$tgt}; } print "Calculating and caching value for $tgt\n"; return $self->{$tgt} = $self->{subref}->($tgt); }; return $work_around; } sub _init { my $self = shift @_; my %arg = @_; for (qw/subref/) { # All valid args $self->{$_} = delete $arg{$_}; } if (keys %arg) { my $bad = join ' ', keys %arg; die "The following args are invalid: $bad"; } return; } package main; tie my $tied_func, 'TieTest', subref => sub {$_[0] * 2}; # Calculate the function values for 1 .. 100 print $tied_func->($_), "\n" for 1 .. 10; # Retrieve cached values print $tied_func->($_), "\n" for 1 .. 10;
If you don't want the function caching - FETCH becomes:
sub FETCH { my $self = shift @_; my $work_around = sub { my $tgt = shift @_; print "Checking for pause\n"; return $self->{subref}->($tgt); }; return $work_around; }
I hope that helps. You should still file a bug report!

Cheers - L~R

Replies are listed 'Best First'.
Re^2: Wierd Behavior With Tie
by rational_icthus (Sexton) on Jun 02, 2006 at 19:42 UTC
    Thank you, that fixed the issue completely, I assume because an entirely new sub is being returned each time? I guess that makes sense.

    Thanks for the caching as well. A definite plus, although I'll probably adjust the subroutine database, adding a cache flag so that I can enable caching at the subroutine level. I just recently made it through Higher Order Perl, and I seem to recall there are times when caching is not in order.

    Problem solved. Thanks!

    Next item on the agenda. Filing a bug report. I'm using ActiveState on an XP box. Do I file the bug report with ActiveState, on CPAN, or both? I've never found a bug before, so never filed a bug report. How does one go about doing this?

    P.S. Also appreciated some of the argument checking idioms. Haven't seen those before. They're very nice. Always looking for a step forward, and those will help me write better code in the future.
      rational_icthus,
      I am glad it worked for you. I don't think it is constructing and returning a new sub each time. I think Perl is over-optimizing. The trick I used was to return a closure over $self which includes the desired subref.

      You are correct, caching isn't always a solution. You might want to check out Memoize for future reference. In many cases, cache is the right solution but with limited resources you need to expire unused items from the cache and only keep the most used recent. The CPAN has all kinds of options. Just search for cache.

      The argument checking is not perfect. There are much better modules such as Params::Validate. Everyone has their own way of doing things. Figuring out what works for you and those responsible for maintaining your code is what is important.

      This problem is not restricted to ActiveState so that's not the proper course of action. If you are not familiar with perlbug then read up on it and send in a minimalistic test case.

      Cheers - L~R

Re^2: Wierd Behavior With Tie
by ikegami (Patriarch) on Jun 02, 2006 at 19:37 UTC

    That doesn't work in 5.6.1. I don't know if that's a problem.

      ikegami,
      I don't have 5.6.1 around to test with but fortunately it worked for rational_icthus's version of Perl. Do you think getting a copy of 5.6.1 to find a work around is warranted or is the filing of a bug report sufficient?

      Cheers - L~R

        I didn't know which version he uses, and which version the people using his code uses. I was just letting him know so there wouldn't be surprises down the line.