in reply to a loop for creating subroutines?

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

Replies are listed 'Best First'.
Re^2: a loop for creating subroutines?
by mascip (Pilgrim) on Aug 27, 2012 at 19:58 UTC

    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 ?

      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)

      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" };
      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