in reply to Creating subroutines on the fly

I was wondering if it is possible to have a subroutine stored as a string and then used as a normal subroutine within a program at run-time.

Have you given sufficient consideration as to why you want to do that? Have you considered any alternatives? If the answer is 'yes' and 'yes' or if you are determined to go this route, you may stop reading this now.

Pulling and executing code directly from a database like that is bound to cause maintenance headaches. It might be more advantageous for you to specify a 'skeleton' subroutine in your code and 'clone' it if you want to define similar subroutines at a later time. The benefit of this approach is that you minimize the domain of valid inputs to your code Basic Coding Tips: Parsimonious Parameterization, and thereby simplify debugging and interpreting the acceptable range of outputs. Even inventing your own 'mini language' would be better than simply pulling in subroutines as strings, because you are basically saying you want your inputs to be any concievable set of perl instructions ... that can't be good.

To translate all this abstract talk into a perl code example, here is an example that creates numerous subroutines that get 'cloned' into your perl code at runtime.

### begin_: init perl use strict; use warnings; my $app; ### begin_: call our 'Clone Generator' CloneSubroutines(); ### begin_: print some results print $app->{show_tag_a}('alpha') . qq'\n'; print $app->{show_tag_b}('bravo') . qq'\n'; print $app->{show_tag_c}('charlie') . qq'\n'; print $app->{show_tag_g}('delta') . qq'\n'; ### --- print &main::show_tag_e('echo'); print show_tag_f('foxtrot'); ### begin_: declare our 'Clone Generator' subroutine sub CloneSubroutines { ### simple example; create different types ### of 'tags' using perl data variables $app->{tag_a} = ['<a>', '</a>']; $app->{tag_b} = ['<b>', '</b>']; $app->{tag_c} = ['<c>', '</c>']; $app->{tag_d} = ['<d>', '</d>']; $app->{tag_e} = ['<e>', '</e>']; $app->{tag_f} = ['<f>', '</f>']; $app->{tag_g} = ['<g>', '</g>']; ### auto-generate (Clone) numerous subroutines ### based on a single subroutine template ### BUGNAG: must use no strict 'refs' pragma for my $tag (sort keys %{$app}) { no strict 'refs'; my $functionName = qq'show_$tag'; ### clone subroutines $app->{$functionName} = sub { my $beg = $app->{$tag}[0]; my $end = $app->{$tag}[1]; my $mid = shift || ''; my $strOut = ''; $strOut = qq'$beg$mid$end'; return $strOut; }; ### copy subroutines *$functionName = $app->{$functionName}; } }###end_sub 1; __END__ <a>alpha</a> <b>bravo</b> <c>charlie</c> <g>delta</g> <e>echo</e><f>foxtrot</f>

Replies are listed 'Best First'.
Re^2: Creating subroutines on the fly
by m-rau (Scribe) on Feb 16, 2005 at 19:15 UTC

    I can imagine a lot of reasone why you want to do this. And this is actually a feature I like much at Perl. Even though I do not use it very often.

    But you have to consider performance issues, if you have evaluated code inside the performance driver (i.e. critical loop) of your script. When Perl sees a variable in your evaluated string, it recompiles it every time . From my current knowledge, I think Perl does not know, if the variable and therefore the string has changed. If not, there is no need to recompile it. But I do not know, if I am up-to-date here.

    Of course, there are solutions for this issue and I do not know, if performance aspects are critical for pander. I just wanted to mention it, since I one was at such a point of Perl programming: Performance tuning for evaluated code segments.