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

I am trying to write a function that makes use of a cache. The problem is that the data in the cache should be initialized as it is used. However, the cache holds onto the raw form, and subsiquent accesses require the data to be initialized again.

Is there a way to make this work?
#!/usr/bin/perl -w use diagnostics; use strict; { my $cache = [Foo->new]; sub access_cache { return @$cache; } } foreach (&access_cache()) { print "before: ", ref($_), "\n"; print "object: ", $_, "\n"; print "after: ", ref($_), "\n"; print "\n"; } foreach (&access_cache()) { print "before: ", ref($_), "\n"; print "object: ", $_, "\n"; print "after: ", ref($_), "\n"; print "\n"; } package Foo; sub new {bless [], $_[0]}; use overload '""' => sub {$_[0] = Bar->new; return $_[0]->[0]}; package Bar; sub new {bless ['barbar'], $_[0]}; use overload '""' => sub {return $_[0]->[0]};
The output of this program is:
before: Foo object: barbar after: Bar before: Foo object: barbar after: Bar
I am trying to get it so that the output will look like this instead:
before: Foo object: barbar after: Bar before: Bar object: barbar after: Bar
I am using This is perl, version 5.005_03 built for i386-freebsd.

I would greatly appreciate any assistance that is offered.

Replies are listed 'Best First'.
Re: Implementing a Data Cache
by sauoq (Abbot) on Jul 09, 2003 at 02:38 UTC
    I am trying to get it so that the output will look like this instead:

    You'll need another layer of reference. Study the following and you'll understand, I think:

    #!/usr/bin/perl -w use diagnostics; use strict; { my $cache = [\Foo->new]; # Additional reference sub access_cache { return @$cache; } } # Additional dereferencing required too. foreach (&access_cache()) { print "before: ", ref($$_), "\n"; print "object: ", $$_, "\n"; print "after: ", ref($$_), "\n"; print "\n"; } foreach (&access_cache()) { print "before: ", ref($$_), "\n"; print "object: ", $$_, "\n"; print "after: ", ref($$_), "\n"; print "\n"; } package Foo; sub new {bless [], $_[0]}; use overload '""' => sub {$_[0] = Bar->new; return $_[0]->[0]}; package Bar; sub new {bless ['barbar'], $_[0]}; use overload '""' => sub {return $_[0]->[0]};

    That produces the output you are looking for.

    -sauoq
    "My two cents aren't worth a dime.";
    
Re: Implementing a Data Cache
by leriksen (Curate) on Jul 09, 2003 at 04:46 UTC
    I did it this way - same effect as saurog's. I believe the problem was you were returning a copy of the array from access_cache - I just changed that to a reference and used that reference
    #!/usr/bin/perl -w use strict; use diagnostics; { my $cache = [Foo->new]; sub access_cache { return \@$cache; } } foreach (@{&access_cache()}) { print STDERR "before: ", ref($_), "\n"; print STDERR "object: ", $_, "\n";; print STDERR "after: ", ref($_), "\n\n"; } foreach (@{&access_cache()}) { print STDERR "before: ", ref($_), "\n"; print STDERR "object: ", $_, "\n"; print STDERR "after: ", ref($_), "\n"; } package Foo; sub new {bless [], $_[0]}; use overload '""' => sub {$_[0] = Bar->new; return $_[0]->[0]}; package Bar; sub new {bless ['barbar'], $_[0]}; use overload '""' => sub {return $_[0]->[0]};
      return \@$cache;

      It's a nit, but that's unnecessarily messy. In this case, just return $cache; rather than taking a reference after dereferencing.

      -sauoq
      "My two cents aren't worth a dime.";
      
      Thanks for the help! It is working correctly now with these changes.