Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Re: Evaluating subroutines from within data

by Anonymous Monk
on Jan 07, 2012 at 01:48 UTC ( #946699=note: print w/replies, xml ) Need Help??

in reply to Evaluating subroutines from within data

I discussed this a while ago in the chatter box, but I can't remember what was suggested.

Do you remember what you asked?

I've read your question four times, and the closest I've seen you come to a question is in the middle :)

I've tried preceding the line with a & and then using eval. The only way that it would work is if I used the full name of the subroutine, which in this case would be Base::HTML::print_definitions(). In the future I may want to print a list of links or use another subroutine I am writing for printing tables. I really don't want to have to use the full names of each subroutine which is part of the text

The following is the code for both print_story and print_definitions which prints the results I expect by themselves. However, I just haven't figured out the best way of getting them to work together. start_html and end_html are the templates I use on every page of my site. The line subroutine just adds tabs to the beginning of a line and then prints a newline after the line. get_hash does what it says, it gets a hash from a data file.

So you want to combine these fragment to do something, but your attempt to use eval to print_definitions isn't quite the best way ....

You you almost have self-contained runnable code, you have some input data, what output do you want to produce?

  • Comment on Re: Evaluating subroutines from within data

Replies are listed 'Best First'.
Re^2: Evaluating subroutines from within data
by Lady_Aleena (Curate) on Jan 07, 2012 at 06:24 UTC

    The following is a sample of what I want to be able to do.

    #!/usr/bin/perl use strict; use warnings FATAL => qw( all ); use CGI::Carp qw(fatalsToBrowser); use lib '../files/perl/lib'; use Base::HTML qw(print_story print_definitions); print_story(*DATA,1); __DATA__ Paragraph that opens the document. 2 Heading for definition list This is the paragraph that precedes the definition list. &print_definitions( file => "some_file_a.txt", headings => ["term","de +finition"],) This is the paragraph that follows the definition list. 2 Heading for next definition list This is the paragraph that precedes the next definition list. &print_definitions( file => "some_file_b.txt", headings => ["term","de +finition 1","definition 2"],) This is the paragraph that follows the next definition list. 2 Heading for the close of the document The paragraph that closes the document.

    In print_story I would like to have something simple like, but I doubt it will be that simple.

    elsif ($line =~ /^\&/) { eval($line); }
    Have a cookie and a very nice day!
    Lady Aleena

      In print_story I would like to have something simple like, but I doubt it will be that simple.

      Sure, it can be that simple, though I might feel safer trying to avoid arbitrary code execution with Safe like

      #!/usr/bin/perl -- use strict; use warnings; use Safe; my $str = <<'__STR__'; &print_definitions( file => "some_file_a.txt", headings => ["term","de +finition"],) &print_definitions( file => "some_file_b.txt", headings => ["term","de +finition 1","definition 2"],) &f() &f ( 1 ) &eff( 'a', "A\tB", 3 ) __STR__ my $namespace = __PACKAGE__; my %dispatch = ( eff => \&f, _default => sub {}, ); open my($in), '<', \$str; while( my $line = <$in> ){ if( my( $sub, $args ) = $line =~ /^\&([^\(\s]+)\s*(.*)/) { print "## $sub $args \n"; my $subref = $namespace->can( $sub ); $subref ||= $dispatch{$sub} || $dispatch{_default}; if( $subref ){ $subref->( length $args ? Safe->new->reval( $args ) : () ); } } } close $in; sub print_definitions { print "print_definitions says [ @_ ]\n\n"; } sub f { print "f says [ @_ ]\n\n"; } __END__ ## print_definitions ( file => "some_file_a.txt", headings => ["term" +,"definition"],) print_definitions says [ file some_file_a.txt headings ARRAY(0xb0b93c) + ] ## print_definitions ( file => "some_file_b.txt", headings => ["term" +,"definition 1","definition 2"],) print_definitions says [ file some_file_b.txt headings ARRAY(0xb0b5ec) + ] ## f () f says [ ] ## f ( 1 ) f says [ 1 ] ## eff ( 'a', "A\tB", 3 ) f says [ a A B 3 ]

      Does that clear things up for you?

        Actually, it didn't. I don't see how to incorporate that into the following. print_definitions will not be the only subroutine that I may want to parse from within the __DATA__ of a document which is being parsed by print_story.

        The very first line is confusing with the two hyphens you put after the shebang. I looked at Safe, and don't understand what the big deal is, since all blocks to me are separate compartments of code to begin with. I take it that $str is equivalent to __DATA__ in your example. I have no idea what my $namespace = __PACKAGE__; is doing. I see you created a dispatch table, but it appears empty of anything that looks like what I'm trying to do.

        print_story is the subroutine I've used the most throughout my site. You've latched onto print_definitions when in the future there could be print_table, print_list, print_monster, print_books, and more. I'd like to put them in __DATA__ when I want to include them within the body of my text.

        sub print_story { my ($source,$html) = @_; my $tab = $html ? 3 : 4; start_html() if $html; while (my $line = <$source>) { chomp($line); if ($line =~ m/^&/) { # This is where the code would go to parse the subroutines # within __DATA__. The subroutines to be parsed would be # preceded with an &. } elsif ($line =~ m/^</) { line($tab,$line); } elsif ($line =~ /^[1-6]\s/) { my ($heading,$text) = split(/ /,$line,2); line($tab,qq(<h$heading>$text</h$heading>)); } else { line($tab,qq(<p>$line</p>)); } } line($tab,qq(<p class="author">written by $user</p>)) if $tab == 3; end_html if $html; }

        If you could point me to a few perldocs to explain some of what you did and how to incorporate it into print_story I'd be grateful.

        Have a cookie and a very nice day!
        Lady Aleena

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://946699]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (10)
As of 2018-06-21 22:39 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (120 votes). Check out past polls.