From: Dan Sugalski Date: 2002-01-21T04:31:22+09:00 Subject: Re: dynamic method creation At 2:04 PM -0500 1/20/02, Mathieu Bouchard wrote: >On Sat, 19 Jan 2002, Dan Sugalski wrote: > >> At 6:19 AM +0900 1/19/02, Leo wrote: >> >"Albert L. Wagner" writes: >> > >> >> I have a need to dynamically create methods with method names >> >> that are not known until run time. Below is my current best >> >> shot. Is there a better way? If methods allowed expressions as >> >> names, and not just as qualifiers, I wouldn't need the eval. >> > >> >You just asked for lisp/scheme type macros. This issue has come >>on this list >> >several times in the past. Everybody understands how great it >>would be to have >> >Ruby macros. It will clearly sky rocket Ruby past Perl/Pyhon. >> >> Dunno about python, but there's nothing new about this for perl. >> Dynamic class and method creation's pretty straightforward, and has >> been for ages. > >Write how you do this in Perl without using eval. You can do it with eval >in Ruby, but the original posters would like something that uses not eval >(not sure why). Sure. If your methods (or subs, whatever) can be synthesized at runtime by just changing data and building a closure, you can do something like: sub make_getter { my $element = $_[0]; *{"__PACKAGE__::get_$element"} = sub {return $_[0]->{$element}}; } which, while nasty and perlish (and potentially a little wrong, as I'm typing this into Eudora without actually testing it), will dynamically generate an element read function for an object that's a hash under the hood. You'd use it like: SomeClass::make_getter("foo"); $var = SomeClass->new(); print $var->get_foo(); and you'd print out the value of the foo entry for the $var object even if the class didn't have a get_foo method defined originally. When you call a method on an object in perl, if the method's not in the class hierarcy for the object perl will look for an AUTOLOAD method and then call that. Lots of perl classes have one that dynamically generate get and set methods for classes as needed at runtime. You can do more than generate accessors--I've a Thread::Object class that, if used as a parent class to an object (perl does multiple inheritance for those following along at home) turns a class' new method into one that creates a new thread for the object, and all other methods into semi-async message passes to the threaded object. (So "$foo->some_method()" actually sends a message to the thread running the $foo object, to be executed when it gets to it, while the thread that made the method call continues on) If, on the other hand, you actually need to completely generate the routine from source (generating a closure's just not good enough), then you need to use string eval. Or one of Simon Cozens' truly evil modules that let you build up chunks of perl 5 bytecode at runtime, but that's not for the faint of heart. -- Dan --------------------------------------"it's like this"------------------- Dan Sugalski even samurai dan@sidhe.org have teddy bears and even teddy bears get drunk