in reply to Re^3: eval problem
in thread eval problem

Your evaluating --$1, where -- is the predecrement operator.

Ah. That was a bad choice of characters in my example.

Also, there is nothing in the eval docs to indicate why this doesn't work:

my $temp = 'xxx$1'; my $repl = eval q{"$temp"};

In other words, why are double double quotes required? Shouldn't the q{} operator return whatever is inside it without interpolation? Wouldn't that be "$temp"? And when "$temp" is eval()'ed wouldn't the qq{} operator around $temp return a string with the $variables interpolated? Or, is it that eval() only does one pass of interpolation over "$temp" leaving me with:

 my $repl = "xxx$1";

and therefore a first pass of interpolation is necessary with qq{} to present eval with "xxx$1"?

Seems pretty straight forward to me

For eval EXPR, the return value of EXPR is parsed and executed as if it were a little Perl program. The value of the expression (which is itself determined within scalar context) is first parsed, and if there weren't any errors, executed in the lexical context of the current Perl program.

Let's test out this eval EXPR thing. First, I need an expression that returns a perl statement that can then be "executed as if it were a little program". The following code seems to produce an expression that I can use:

use strict; use warnings; use 5.010; my $x = 10; my $result = sprintf '%s', 'my $y = $x;'; say $result; --output:-- my $y = $x;

The return value of the sprintf expression is the string that is displayed. Ok, now I'm going to eval that expression. According to the docs you quoted, the value of the expression will be "executed in the lexical content of the current Perl program"--whatever that means. I'll try using eval() and see what happens:

my $x = 10; eval (sprintf '%s', 'my $y = $x'); say $y; #line 14 --output:-- Global symbol "$y" requires explicit package name at 2perl.pl line 14. Execution of 2perl.pl aborted due to compilation errors.

I thought I followed the instructions in the docs to the letter, but eval EXPR just spits out errors. What about the block form of eval(): eval BLOCK? The docs say:

the BLOCK is parsed only once‐‐at the same time the code surrounding the "eval" itself was parsed‐‐and executed within the context of the current Perl program.

This seems much easier; no sprintf necessary:

my $x = 10; eval {my $y = $x}; say $y; #line 14 --output:-- Global symbol "$y" requires explicit package name at 2perl.pl line 14. Execution of 2perl.pl aborted due to compilation errors.

The heck with the descriptions, I'll examine a couple of examples in the docs and figure it out by myself. Hmmm...none of the examples in the docs will work either because they are incomplete.

So...no. The docs do not seem straightforward to me.

Replies are listed 'Best First'.
Re^5: eval problem
by ikegami (Patriarch) on Dec 04, 2009 at 02:18 UTC

    Shouldn't the q{} operator return whatever is inside it without interpolation?

    Yes. The only special sequences in single quotes are: backslash-backslash, backslash-delimiter and delimiter.

    Wouldn't that be "$temp"?

    Yes

    $ perl -le'print q{"$temp"}' "$temp"

    And when "$temp" is eval()'ed wouldn't the qq{} operator around $temp return a string with the $variables interpolated?

    Yes. The value of $temp is interpolated.

    $ perl -le'$temp=q{Bread was $1.50}; print eval q{"$temp"}' Bread was $1.50 $ perl -le'$temp=q{Bread was $1.50}; print "$temp"' Bread was $1.50

    This seems much easier; no sprintf necessary:

    I don't know why you used sprintf in any of the examples. You do realize that

    '...'
    is just as much an expression as
    sprintf('%s', '...')

    right? An expression is a piece of code that can be used as an operand. That includes simple values such as a string.

    I thought I followed the instructions in the docs to the letter, but eval EXPR just spits out errors.

    Not true. eval EXPR doesn't spit out errors. It places them in $@ and you didn't even check $@. The message you posted came from say $y;.

    What you're missing is that Perl programs are compiled and executed in their own scope, usually called "file scope". Think of the eval code as being inside a do{}. Yeah, that could be made more explicit.

    $ perl -E'use strict; my $x = 10; eval q{ my $y = $x; }; say $y' Global symbol "$y" requires explicit package name at -e line 1. Execution of -e aborted due to compilation errors. $ perl -E'use strict; my $x = 10; eval q{ my $y = $x; say $y };' 10 $ perl -E'use strict; my $x = 10; my $y; eval q{ $y = $x; }; say $y' 10 $ perl -E'use strict; my $x = 10; my $y = eval q{ $x }; say $y' 10

    eval {my $y = $x};

    Don't try to apply the docs for eval EXPR to eval BLOCK at all. It's a completely different operator. In Java, C++ and Perl6, it's known as try. It won't help you at all here.

Re^5: eval problem
by ikegami (Patriarch) on Dec 04, 2009 at 04:57 UTC

    I missed this question of yours originally

    Or, is it that eval() only does one pass of interpolation over "$temp"

    eval EXPR doesn't interpolate. It parses and executes the Perl code it is provided.

    As for Perl, it doesn't interpolate recursively. Nothing I know does. (Perl, bash, Template-Toolkit, ...) quotemeta would become the most used function if it did.