http://qs321.pair.com?node_id=148470

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

I'm trying to write some code which dynamically creates 'my' variables for evaluation by some user inputted perl code. What I want is for perl to catch unregistered variables which is why I want this to run under "use strict"

My problem is the dynamic creation of variables in the current scope, I'm trying the following.

my $bar = "fred";
eval "my \${$bar} = 'foo';";

print $fred;

I want this to print "foo", but I get errors, is there any way to do this?
  • Comment on creating dynamically named 'my' variables

Replies are listed 'Best First'.
Re: creating dynamically named 'my' variables
by japhy (Canon) on Mar 01, 2002 at 04:07 UTC
    No, no, no, no, and no. Please do not try this. Use a hash instead. Whenever you think of making dynamic variables, use a hash instead.
    my %user_vars; $user_vars{$var_name} = $var_value;

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a (from-home) job
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      That's fine for most things, but as stated I want perl to catch accesses to variables that don't exist in the user inputted perl code.

        With great trepidation, I have to say that there is a way to pull this off. You could check out PadWalker. From the description:

        PadWalker is a module which allows you to inspect (and even change!) lexical variables in any subroutine which called you. It will only show those variable which are in-scope at the point of the call.

        This software appears to be brand new, so use it with care. What I want to know, however, is how you can justify a need for something like this. Yes, I've read the rest of the thread about how you don't need to worry about malicious code because it's being supplied by programmers in your company (what if they write really awful code? what if one of them is quitting and has a nice time bomb in the code?), but I still wonder what problem you are really trying to solve. For the vast majority of programmers, when the apparent solution is terribly convoluted and requires "tricks" to pull off, this suggests that you should rethink the problem. In other words, if you back up a step and let us know what you're trying to do, maybe we can offer safer alternatives.

        Cheers,
        Ovid

        Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

        Hmmm, I'm not exactly sure what it is that you are trying to do but you may want to investigate the Safe module for the evaluation of supplied Perl code. This module allows you to evaluate Perl code in a contained compartment where restrictions can be imposed on allowed and disallowed operators - This can be very important where the code is derived from a potentially unsafe source.

         

        perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'

        Well, use strict to do this.

        Or, use a tied hash that catches references to non-existent keys.

(tye)Re: creating dynamically named 'my' variables
by tye (Sage) on Mar 01, 2002 at 06:52 UTC

    I've wanted to do this before. That is just one reason why I want to be able to write:     eval "my \$$bar;" if $workAround BEGIN; where the statement-modifier BEGIN prevents the introduction of a new scope and stringy eval is changed to (be able to) avoid introducing a new level of scope.

    But I'd probably do what you want with something like:

    my $code= <FILE>; eval "my \$$bar;\n#line 1 "file"\n$code"; die $@ if $@;
    I think.

            - tye (but my friends call me "Tye")
Re: creating dynamically named 'my' variables
by clemburg (Curate) on Mar 01, 2002 at 11:20 UTC

    Maybe it might be worth the time to take a look at how the Damian handled that situation in Parse::RecDescent, which IMHO has to solve the same problems as you describe.

    Christian Lemburg
    Brainbench MVP for Perl
    http://www.brainbench.com

Re: creating dynamically named 'my' variables
by rrwo (Friar) on Mar 01, 2002 at 04:42 UTC

    Wait a minute! You want to create variables given names by the user?!?!! That's pretty dangerous, unless you trust the user wholeheartedly.

    Use a hash instead.

    You can use symbolic references to do this:

    my $bar="fred"; no strict refs; $$bar="ethel"; print $fred, "\n"; print $$bar, "\n";

    but it doesn't work as a "my variable". In part I think because the scope is limited to within the eval. Ooutside the eval, the variable goes way.

    I really don't recommend you do this, though.

Re: creating dynamically named 'my' variables
by Ryszard (Priest) on Mar 01, 2002 at 04:58 UTC
    It sounds like to me you want your perl script to get another perl script and either execute it or evaluate it's syntax. - Are you writing a perl parser?
      Actually I'm writing a data to marked up data compiler which multiple input types at the frontend and configurable (via perl script) at the backend. I'm writing it in Perl so I want perl to eval the (perl) configuration.
        Maybe you would be better off using package variables and force them all into one specific package?

        -Lee

        "To be civilized is to deny one's nature."
Re: creating dynamically named 'my' variables
by shotgunefx (Parson) on Mar 01, 2002 at 09:35 UTC
    There is probably a much better way to do what you want BUT... the only way I know of getting text outside of your script compiled in the current lexical scope is to use the solution from the Cookbook.
    eval `cat /whereever/whatever.cfg`;


    -Lee

    "To be civilized is to deny one's nature."
Re: creating dynamically named 'my' variables
by ajwans (Scribe) on Mar 01, 2002 at 05:19 UTC
    Perhaps what I need to do is to create all my variables within a namespace, enter that namespace, then destroy the namespace when I'm finished with it.

    Can anyone point me to docs for namespaces?
      See do FILE, and return a reference to a hash. That's much safer than eval STRING.