http://www.perlmonks.org?node_id=990052


in reply to Re: a loop for creating subroutines?
in thread a loop for creating subroutines?

More solutions, cool :-)

I see that lanX's answer is the "good" clean answer, but i don't like it as a stand-alone answer, as the code then looks ugly (i forgot to say it's a method, not a function) :

$S{light}->($self, 10);
instead of
$self->light(10)
(I used %S instead of %mysubs. And i use Moose, so i need to pass $self as an argument).

So, what i did was to use AUTOLOAD, to call these subroutines :

sub AUTOLOAD { my $self = shift; my @args = @_; # Retrieve the method name, without the Package name my $name = our $AUTOLOAD; $name =~ s/.*://; # Check if this is one of the functions we declared croak "Undefined method : $name" if !$S{$name}; # Call the appropriate method return $S{$name}->($self, @args); }
which enables me to call
$obj->light(10);

Now, the question is : is that clean, and are there "cleaner" (and why) solutions.

I must say i'm not in love with the 'eval' solution ( but it works :-) ).

Would it be cleaner to do

foreach my $name (@names) { my $name = $S{$name}; }
But then i will also need to put $self as an argument all the time.

What about installing them in the import table : is it cleaner than using AUTOLOAD ?

Replies are listed 'Best First'.
Re^3: a loop for creating subroutines?
by philiprbrenan (Monk) on Aug 27, 2012 at 20:52 UTC

    With methods:

    use feature ":5.14"; use warnings FATAL => qw(all); use strict; use Data::Dump qw(dump); sub Mine() {package __SUB__; eval "sub $_ {say \"$_\"}" for qw(hello goodbye); bless {} } my $a = Mine(); $a->hello(); $a->goodbye(); __END__ Produces: hello goodbye

    There is a method to his madness. (Hamlet)

Re^3: a loop for creating subroutines?
by Anonymous Monk on Aug 28, 2012 at 06:58 UTC

    If it's a class, I would consider both the symbol table and the AUTOLOAD ways good; although AUTOLOAD is safer in the respect that it won't override any existing methods.

    Personally, I'd just install the methods straight into the symbol table as it feels clean and should be slightly more performant. And safety -- you can avoid overwriting any subroutines at install time:

    warn "baz already defined" if defined *{__PACKAGE__ . "::baz" };
Re^3: a loop for creating subroutines?
by LanX (Saint) on Aug 28, 2012 at 08:47 UTC
    I've shown you two ways and the second works for objects too. (in perl package == class)

    Don't know too much about moose.

    But if you ask for "the cleanest" approach, better avoid metaprogramming!

    Just define two getters and use a fat comma to get rid of the quoting.

    $object->cell(light => 10); $object->time(light => $timestamp);

    I like metaprogramming, but here it's over the top.

    And this certainly works with moose too!

    Cheers Rolf