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”;
Perl

Avatar of undefined
Last Comment
Chunhua Du

8/22/2022 - Mon
SOLUTION
wilcoxon

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
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
wilcoxon

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.
Chunhua Du

ASKER
In the nesting eval function, if I want to use single quote on the parameter of eval, how should I code

thanks
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
wilcoxon

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.
Chunhua Du

ASKER
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
wilcoxon

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
Chunhua Du

ASKER
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
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
noci

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.
Chunhua Du

ASKER
Thanks, I would try it
Chunhua Du

ASKER
Do you mean \\\$->\\+\\+\\\$
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Chunhua Du

ASKER
How can I understand 'double', I am not sure double what
ASKER CERTIFIED SOLUTION
noci

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
wilcoxon

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
wilcoxon

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Chunhua Du

ASKER
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"
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
noci

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.
Chunhua Du

ASKER
In my code:

print $$varName;

at this line, I hope to get value of $a1, why getting nothing? Must it use eval?
Chunhua Du

ASKER
By my understanding, if I write:

$$varName

in level N of eval, $varName must be defined and get value in level N-1
Your help has saved me hundreds of hours of internet surfing.
fblack61
Chunhua Du

ASKER
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
noci

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Chunhua Du

ASKER
But why this works:

$str = m{$pattern};
for($xx = 1; $xx <= 2; $xx++)
{
      print $$xx;
}
noci

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...
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
wilcoxon

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).
Chunhua Du

ASKER
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";
}
Chunhua Du

ASKER
I have try your code with:

no strict 'refs';

I get empty output.
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
wilcoxon

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
wilcoxon

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Chunhua Du

ASKER
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!