in reply to Re^2: defining methods on the fly
in thread defining methods on the fly

Yes, the cache is rebuilt. You're just resetting it. All new method lookups after it's been reset are cached until it's reset again. Here's some code I ran in bleadperl which includes a function to look at the version number of the method lookup cache. Things that you do once during setup aren't usually of any account. It's worth blowing your cache then because you get all the utility of whatever it is that you stopped to do and you don't usually incur lots of extra runtime work. When you blow your cache during your run you impact your overall performance because now you're penalizing all the time consuming regular stuff too.

use B 'sub_generation'; sub show_cache_version { print sub_generation, "\n" } show_cache_version; # 554 { show_cache_version; # 554 local *call = sub { }; show_cache_version; # 555 <- @ISA cache reset } show_cache_version; # 555

⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Replies are listed 'Best First'.
Re^4: defining methods on the fly
by jdhedden (Deacon) on Aug 03, 2006 at 19:14 UTC
    The following modification does not assign to a glob. Do this avoid the cache reset issue?
    #!/usr/local/bin/perl use warnings; use strict; use Want; sub lvalueMethod($) { my ($name) = @_; my ($package) = caller; no strict 'refs'; *{$package . "::" . $name} = sub :lvalue { my $self = shift; if (!want('LVALUE') && ref($self->{$name}) eq 'CODE') { goto &{$self->{$name}}; } $self->{$name}; }; } { package Foo; sub new { bless {}, shift; } main::lvalueMethod("bar"); } my ($x) = Foo->new(); print "$x\n"; $x->bar = 5; print $x->bar, "\n"; $x->bar = sub { print( @_, "\n" ); }; $x->bar("Hello World");

    Remember: There's always one more bug.
      From my understanding of his response that avoids the issue.
      The following modification does not assign to a glob.

      Apologies if I'm misunderstanding something here, but isn't the following code assigning to a glob?

      *{$package . "::" . $name} = sub :lvalue {

      Update: Thanks for the reply -- I was indeed "misunderstanding something here."

        Apologies if I'm misunderstanding something here, but isn't the following code assigning to a glob?
        *{$package . "::" . $name} = sub :lvalue {
        True, but that wasn't what I was referring to. The above is only executed once. The concern was with the following line in the original code that was executed every time the method was called:
        local *call = sub { $self->{$name}->(@_); };
        By removing that line, my suggested code should not suffer from the method cache reset performance penalty that occurs each time the method in the original code is called.

        Remember: There's always one more bug.