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

I checked our own SuperSearch for this, and it does not seem as though it should be hard, but I cannot seem to figure it out. Maybe it is brain fog. Anyway, consider:
$data{bar}{code} = 'print $foo;' ... eval $data{bar}{code};
Now what I want to have happen is for eval to say, "uh-oh, $foo is not defined. I will look in $data{bar}{values}{foo} to see if it is there." I'm flexible on my data types, but I want the stuff to be evaluated to just use simple variables.

This is to try to avoid symbolic references. I'm developing code where snippets are found in an XML doc and they refer to tag names so the above might come from

<data name="foo" value="hello" /> <prog> print $foo; </prog>
I need it to be as simple as possible to edit the XML so I don't want hash refs there. I want to avoid symbolic refs for the usual reasons. Any suggestions would, of course, be welcome.

Thanks, --traveler

Replies are listed 'Best First'.
•Re: Supplying a value for an undefined variable
by merlyn (Sage) on Jan 15, 2003 at 23:42 UTC
    Take a look at Safe. While you wouldn't be using it for its protection (you can leave all opcodes enabled, for example), it has a nice "top-level namespace" management interface. Your package variables can be established into the appropriate compartment, and then the code can also be evaluated there. That should do well.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      merlyn, this looks as though it will fit the bill directly. I need to play with namespaces and sharing a bit, but I think this will make things farily simple. Thanks!

      --traveler

Re: Supplying a value for an undefined variable
by Coruscate (Sexton) on Jan 15, 2003 at 23:42 UTC

    My solution assumes and requires that the variable name within the code is followed directly by a semi-colon. To test out my example, run it with the my $foo = 'hi'; declaration, then comment that line out. Good luck.

    #!c:/perl/bin/perl -w use strict; my %data = ( 'bar' => { 'code' => 'print $foo;', 'values' => { 'foo' => 'hello' } } ); my $foo = 'hi'; eval $data{bar}{code}; if ($@) { $data{bar}{code} =~ s/\$([^;]+);/\$data{bar}{values}{$1};/g; eval $data{bar}{code}; }