Link to home
Create AccountLog in
Avatar of Chunhua Du
Chunhua Du

asked on

Why this perl code about eval not work

Code is here:

my $a1 = ‘a1_v’;
my $c1;
my $varName;

my $code = qq(
      \$varName = ‘a1’;
      eval(‘\$c1 = \$\$varName;’);
);

eval($code);

# I hope this line print a1_v, but print nothing
print “$c1\n”;
SOLUTION
Avatar of wilcoxon
wilcoxon
Flag of United States of America image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Avatar of Chunhua Du
Chunhua Du

ASKER

could I understand in this way: every layer of eval function add in code string, add \\ to begin of $ in parameter of added eval function?

thanks
Yes.  Generally, for every level of eval, add \ per level (which means \\ for beyond the first).

Anytime you have an eval that doesn't work, the first thing to check on is the escapes and quotes and try debugging if they are what you want for the level of eval nesting you are using.
In the nesting eval function, if I want to use single quote on the parameter of eval, how should I code

thanks
I don't think you can in this case (not positive) as you have variables at different nesting.  Why do you want to use single quotes?

Let me start even more basic - what are you trying to do with the nested evals?  You can probably do something else that would be simpler and much more efficient.
I want to know why this works:

my $code = qq(
   \$str =~ m"$pattern";
   for(\$xx = 1; \$xx <=2; $xx++)
   {
      eval('\$backRef = \$\$xx;');
      push(\@\$backRefArr, \$backRef);
   }
);

eval($code);

print "@$backRRefArr";
SOLUTION
Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
In my last code, variable $refBack and @refBackArr are defined out of $code

$xx++ in my last post is mistake, in my code it is \$xx++, it is my mistake sorry for this
not need to add a \  you need to escape everythin double

so \ -> \\   $ needs \$  etc.      $var -> \$var
Each needs to be escaped again...:   \$var -> \\\$var
Next level:                                              \\\$var -> \\\\\\\$var
etc.
Thanks, I would try it
Do you mean \\\$->\\+\\+\\\$
How can I understand 'double', I am not sure double what
ASKER CERTIFIED SOLUTION
Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
To rephrase what noci (and I) are saying...

For each nesting of eval that something should be evaluated at, you need to add an escape.  qq(...) is equivalent to double-quoting.

Given the example:
my $code = qq(
   \$str =~ m"$pattern";
   for(\$xx = 1; \$xx <=2; $xx++)
   {
      eval('\$backRef = \$\$xx;');
      push(\@\$backRefArr, \$backRef);
   }
);

eval($code);

print "@$backRRefArr";

Open in new window


$pattern will be evaluated when $code is defined
everything with \x becomes x when $code is defined
everything that had \x is evaluated when the first eval occurs (except the things in the second eval because they are enclosed in single quotes)
the single quoted string is then eval'd by the second eval
SOLUTION
Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Why this not work:

my $a1 = 'a1_v';
my $varName;

my $code = qq(
      \$varName = 'a1';
      print \$\$varName;
);

eval($code);

# This do not work, either
$varName = 'a1';
print "$$varName"
Why should it:
I translated your $code to the equivalent $code2...
my $a1 = 'a1_v';
my $varName;

my $code = qq(
      $varName = 'a1';
      print \$\$varName;
);
my $code2 = "
    $varName = 'a1';
    print \$\$varName;
    ";

print "code=$code\n";
print "code2=$code2\n";
#(That should explain the first part... qq is realy the same as "..., if you have an ebcdic system qq( ) is simpler than just "...

# This do not work, either
$varName = 'a1';
print "\$$varName"
#This does what you told it to do print $ and the contents of $varName:   result: $a1    (without line feed)...

Open in new window



You may meant it to do:

$varName = 'a1';
eval( "print \$$varName; " );
print "\n";
eval( "print \"\${$varName}\"; " );
print "\n";
eval( "\$x = \"\${$varName}\"; print \$x;" );
print "\n";

Open in new window


again look at the intermediate results:
$varName = 'a1';
print( "print \$$varName; " );
print "\n";
print( "print \"\${$varName}\"; " );
print "\n";
print( "\$x = \"\${$varName}\"; print \$x;" );
print "\n";

Open in new window


Which requires proper quoting, including the " getting quoted, if needed.
In my code:

print $$varName;

at this line, I hope to get value of $a1, why getting nothing? Must it use eval?
By my understanding, if I write:

$$varName

in level N of eval, $varName must be defined and get value in level N-1
I mean that get value of $a1 by $$varName, $varName has string value 'a1'.

For example: $a1 has value 'v1', I want $$varName return value 'v1'. I am not sure whether it must use eval here
SOLUTION
Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
But why this works:

$str = m{$pattern};
for($xx = 1; $xx <= 2; $xx++)
{
      print $$xx;
}
They work at printing nothing?.... as there is quite some missing context. Syntax is correct though.
Anyway what is $pattern...
The pattern isn't matched to anything using =~ ....

Please try the code fragments you wish us to evaluate First as such and describe what you get and what you expect...
Doing something like this:
my $a1 = 'v_1';
my $varName = 'a1';
{ # begin closure
no strict 'refs';
print $$varName, "\n";
} # end closure

Open in new window

does not require an eval.  That is a symbolic ref and works fine.

You are doing "use strict; use warnings;" in your code, right?  If not, you ALWAYS should be as it will catch a lot of errors (and I assume you are which is why I put "no strict 'refs'" since strict disallows symbolic references and you should only allow them where expected).
Full code in my last post:

my $s1 = 'xxa1xxb2xx';
$s1 =~ m{(a\d+).*?(b\d+)};

for($xx = 1; $xx <= 2; $xx++)
{
      # why this line get value 'a1' and 'b2' without eval
      print "$$xx";
      print "\n";
}
I have try your code with:

no strict 'refs';

I get empty output.
Your code works fine because it uses symbolic refs.  $$xx evaluates to $1 and then $2.

Apparently I shouldn't do symbolic refs or evals from memory (my code doesn't work as posted and I don't see why).  I'll double-check it later and report a snippet that works...
SOLUTION
Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Thanks to all your help these days. I have understood and got ways to do on those issues by your posts.

I think it is time to stop.

Thanks everyone who help.

Happy New Year!