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

Dear Monks,

Let's say my Perl code contains a string which contains a valid Perl function.

my $func = "sub foo { return 'bar'; }";

If I use eval() I will not get any new function to call. So ... my question is: How can I ask perl compiler to compile this new function and put it in to service? Dynamically at run time - of course.

Replies are listed 'Best First'.
Re: Perl generating embedded Perl
by BrowserUk (Patriarch) on Feb 06, 2010 at 14:41 UTC

    If you eval a string containing a named sub definition, it gets installed into the current package:

    c:\test>perl -E"eval 'sub Foo{ return 12345 }'; print Foo();" 12345

    If you want to create an anonymous sub and get a reference to it into a variable:

    c:\test>perl -E"$f = eval 'sub { return 12345 }'; print $f->();" 12345 c:\test>perl -E"$f = eval 'sub { return "bar" }'; print $f->();" bar

    That works also.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Thank you, I thought I need to use something called "dynloader" from core which is used by source filters but this happened to be more easier that I could imagine :-)

      I got my second Perl experiment to work exactly the way I wanted by using this anonymous sub reference solution.

      Here is my extremely fast precompiled Embedded Perl HTML template for your reference.

      use 5.010; use strict; use warnings; our $start_time = time; #Embedded perl HTML template compiler object class package HTML::template; #Preloads new template object: #@_ = class, embedded perl/html input source sub new { my ($class, $input) = @_; $input //= $_; #Slurp the source template open my $fh, "<", $input or die "$! \"$input\""; local $/; my $slurp = <$fh>; close $fh; #Extract perl script from the template my $content = \$slurp; my $position = 0; my $script = "sub {\n\# line 1 \"$input\"\n"; #Scan html comment tags while ( $slurp =~ /<!--(?<cmd>.*?)-->/gso ) { #Insert text block $script .= "print substr(\${\$content},$position,$-[0]-$positi +on);\n"; #Translate line numbers my $line = ( substr($slurp,0,$position) =~ tr/\n// ) + 1; #Insert perl block using fixed line number $script .= "\# line $line\n$+{cmd}\n"; #Advance to next block $position = $+[0]; } #Insert the last text block $script .= "print substr(\${\$content},$position);}"; #Precompile script my $compiled = eval($script) or die; #Define template object list bless [$content, $compiled], $class; } #Execute the template object ##@_ = class, html output target sub run { my ($self, $output) = @_; my ($content, $compiled) = @{$self}; $output //= $_; #Redirect output local (*STDOUT); open(STDOUT, ">", $output); #Excute precompiled script $compiled->(); } #Sample program utilizing HTML::template my $sample_input = <<'END'; Numbers generated at <!--print $start_time;--><br> <!--for(my $x = 1; $x < 5; $x++) {-->Number=<!--print $x;--><br> <!--}-->Time used <!--print time - $start_time;--> seconds.<br> END my $template = HTML::template->new(\$sample_input); my $sample_output = ''; $template->run(\$sample_output); print $sample_output; #Output from sample_template Numbers generated at 1265498059<br> Number=1<br> Number=2<br> Number=3<br> Number=4<br> Time used 0 seconds.<br>
        Perl code + Template = Text::Template
        use warnings; use strict; use Text::Template qw(fill_in_string); print fill_in_string(<<'EOT'); Numbers generated at { $start_time = time }<br>{ for my $x (1 .. 4) { $OUT .= "\nNumber=$x<br>" } } Time used { time - $start_time } seconds.<br> EOT
Re: Perl generating embedded Perl
by Anonymous Monk on Feb 06, 2010 at 14:33 UTC
    Don't, use a module (like Module::Pluggable)
    eval "sub foo { return 'bar'; } ; 1"; warn 'foo'->(); __END__ bar at - line 2.