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

hi all,
here is a problem with the dynamic string passed to eval.
but the same eval works with the a static string.
# $arg is built in a for loop like this. $arg .= "\"" . $str . "\", "; ##### after building $arg will be "bkund", "454545" chop $arg ; chop $arg ; # the below line works doesn't work with eval my $call = ' $jobs->$func ($arg) ' ; # this is actual data $arg - the below line works with eval # my $call = ' $jobs->$func ("bkund", "454545") ' ; my %jobstats = eval $call;
whats could be the problem??
thanks
rsennat

Replies are listed 'Best First'.
Re: problem in using eval strings
by Tanktalus (Canon) on Dec 02, 2005 at 16:02 UTC

    Might I recommend a different way to build up your string which may be a bit closer to what you're trying to accomplish? (I'm an advocate of making my solutions look like the problem, not like the solution.)

    I'm assuming your "for loop" is using a list such as @args.

    my $call = '$jobs->$func(' . join(', ', map qq{"$_"}, @args) . ')'; my %jobstats = eval $call;

    I'm avoiding all the chops as I don't add more commas than needed. That said, even the way you're doing it, you could remove the chops - trailing commas don't bother perl at all. My guess is that perl would parse and discard the comma faster inside the compiler than by using chop anyway.

    Anyway, this code builds your method call in exactly the same way that you normally do. You convert your arguments to be quoted (converting one list to another is a map), you put commas between them (putting a string - even if it were an empty string - repeatedly between other strings is a join), and you put stuff before and after (with the dot operator).

    Using the escape (backslash) as has already been suggested is one way to do this when you need to use double quotes. But I find escapes to be distracting and like to avoid them when reasonably possible.

    Belgarion is correct in what your problem is. I'm just offering another way to approach your basic problem that may prove better.

    Note: Even better for this scenario is:

    my %jobstats = $jobs->$func(@args);
    There's no need, in this scenario, to use eval at all. But I'm presuming you have something that becomes a bit complex that you want to use eval for - such as @args having "$foo" as one of its values, and eval STRING will then see "$foo" and interpolate the $foo to be whatever $foo contains. Which is generally a bad idea when you can avoid it - use hashes.

Re: problem in using eval strings
by Belgarion (Chaplain) on Dec 02, 2005 at 15:43 UTC

    My guess is that the line:

    my $call = ' $jobs->$func ($arg) ' ;
    

    Is not interpolating (expanding) the $arg variable. Use double quotes and escape the dollar signs, like so:

    my $call = " \$jobs->\$func ($arg) " ;
    
Re: problem in using eval strings
by mrborisguy (Hermit) on Dec 02, 2005 at 16:53 UTC

    What I wonder, and maybe this isn't possible for some reason, but why do you need an eval? Can't you replace

    $arg .= "\"" . $str . "\", ";

    with

    push @args, $str

    and then instead of

    my %jobstats = eval $call

    just use

    my %jobstats = $jobs->$func( @args )

    I like to reduce the number of times I have to use eval, and I think most monks would agree with me. Try to get rid of it if possible.

        -Bryan

Re: problem in using eval strings
by ikegami (Patriarch) on Dec 02, 2005 at 15:49 UTC
    What does perl say is the problem?
    my %jobstats = eval $call; die("eval failed: $@") if $@;
Re: problem in using eval strings
by rsennat (Beadle) on Dec 02, 2005 at 15:55 UTC
    perl doesn't say any error.

    but the string is considered a single string, "bkund", "454545", i.e, that whole string is passed as a single argument to that function, though its a 2 argument.

    what can be done to resolve this??