Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

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
Re^2: Evaluating subroutines from within data
by Lady_Aleena (Deacon) 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?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://946699]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (5)
As of 2015-07-05 23:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (68 votes), past polls