in reply to defining methods on the fly

Just keep in mind that you invalidate your method-lookup cache everytime you invoke that code. Normally once perl knows what function belongs to a method call on an object from a particular class it's able to cache that and not do the work of looking all around ISA. Whenever you change something that could cause the cached value to be incorrect, perl discards all it's cached information. Those somethings are changing @ISA anywhere or altering the symbol table. Glob assignments like you did are one of those explicit reasons. Your code won't even work unless perl does this.

So just be aware you're making perl's OO slow for you. It has to do work that most people's perl won't have to.

⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Replies are listed 'Best First'.
Re^2: defining methods on the fly
by flogic (Acolyte) on Aug 03, 2006 at 14:37 UTC
    hmm... Does the cache get rebuilt? And does the second glob assignment cause the same problem? Class::Accessor::Lvalue (mentioned above) uses an eval. Is the eval faster?

      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

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        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.