Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

How do I create subroutines on the fly, and how are they accessed?

Replies are listed 'Best First'.
Re: Dynamic Subroutines?
by Dominus (Parson) on Mar 30, 2001 at 20:08 UTC
    Answer #1: You create them with eval:
    sub create_subroutine_to_return_constant { my ($name, $constant) = @_; my $code = "sub $name { return $constant }"; eval $code; }
    Then you access them the same as any other subroutine:
    create_subroutine_to_return_constant('PI', 3); $z = PI(); # returns 3
Re: Dynamic Subroutines?
by Dominus (Parson) on Mar 30, 2001 at 20:16 UTC
    Answer #2: If the code will always be the same, and only the values of some variables will be different, you can make anonymous functions like this:
    sub create_subroutine_to_return_constant { my ($constant) = @_; my $newsub = sub { return $constant }; return $newsub; }
    Then you call it using the -> notation:
    my $PI = create_subroutine_to_return_constant(3); $z = $PI->(); # returns 3
    This technique is a lot more interesting than the example I showed. But I didn't want to give too much information at once.

    Perhaps you could say a little more about what you are trying to accomplish here.

Re: Dynamic Subroutines?
by Malkavian (Friar) on Mar 30, 2001 at 20:15 UTC
    I think you're looking for anonymous subroutines.
    A quick example:
    # Compile some anonymous subroutine code in a variable my $code='sub { print "A quick sample\n";}'; # Turn this into a reference to some executable code my $subroutine=eval $code; # Invoke the subroutine you just made &$subroutine();

    This is just a quick example, hope it helps.

    Malk
Re: Dynamic Subroutines?
by suaveant (Parson) on Mar 30, 2001 at 20:25 UTC
    If you feel really brave you can assign an anonymous subroutine a name with a glob. I.E.
    *PI = create('3.14159'); Π sub create { my(@foo) = @_; return sub { print "@foo\n"; }; }
    You need the my declaration, it makes the closure work. - Ant
Re: Dynamic Subroutines?
by Anonymous Monk on Mar 30, 2001 at 20:37 UTC
    What I am trying to do is use the events that are defined in Win32::Gui. In my script I query a list and dump them into a ListView. Once they are in the ListView I want to be able to click on an element in the ListView and have its detail display in a Textfield. In order to do this I need to use the follow event:

    ItemClick(ITEM) Sent when the user selects an item in the ListView; ITEM specifies the zero-based index of the selected item.

    so in order to get the desired results I have to create a subroutine for every item in my ListView. When I code it up statically it works.

    sub ResultView_ItemClick(2) { $Display->results->Text(${$List{2}}{message}); }
    However when I use :
    my $code = "sub ResultView_ItemClick($count) { $Display->results->Text +(${$List{$count}}{message});}"; eval $code;
    when I am building my list whenever I click on an element I generate an error. When I run the code it seems that the GUI::Dialog reconizes that I created the subs but it throws an error "Undefined subroutine &main::ResultView_ItemClick"
      Ahhh, yes... I would really suggest the Advanced Perl Programming book from O'Reilly. It cover similar things...

      You actually do not need a closure, you should simply be able to do the following:

      *ResultView_ItemClick = sub { $Display->results->Text(${$List{$_[0]}}{ +message}); }; ResultView_ItemClick(2);
      That should do what you want.. if I understand correctly.
      - Ant