Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re^2: Please help me understand string eval better

by perltux (Monk)
on Jun 13, 2017 at 03:25 UTC ( [id://1192646] : note . print w/replies, xml ) Need Help??


in reply to Re: Please help me understand string eval better
in thread Please help me understand string eval better

You say '$$var' is a literal but in my experiments the value stored in $$var is actually being used during eval so it's not a literal string at run-time when eval runs it.
That's why I'm wondering what differences there are between option 1 and option 3.

I got to this because $$var can contain a number with a leading zero, which with option 1 gets interpreted as octal by eval while with option 3 the leading zero is ignored, so I know these options aren't the same, I just don't know what other effects using option 3 instead of option 1 can have.

Replies are listed 'Best First'.
Re^3: Please help me understand string eval better
by huck (Prior) on Jun 13, 2017 at 03:40 UTC

    That's why I'm wondering if between option 1 and option 3 there is a difference.

    use strict; use warnings; my $foo='$ans='; my $var=\$foo; my $transf='5;' ; my $r5='$ans="hithere";'; my $var5=\$r5; testit("$$var$transf"); testit("${$var}$transf"); testit($$var.$transf); testit('$$var'.$transf); sub testit { my $ans; my $string=shift; $ans='???'; my $eret=eval $string; printf 'String:%-20s',$string; printf ' $ans:%-10s',$ans; printf ' $eret:%-10s',$eret; print "\n"; } # testit
    Result
    String:$ans=5; $ans:5 $eret:5 String:$ans=5; $ans:5 $eret:5 String:$ans=5; $ans:5 $eret:5 String:$$var5; $ans:??? $eret:$ans="hithere";
    Yea i think there is a difference.

    And i dont think you would be talking about "run time" if you understood the multiple compile and run times involved. First your script containing the eval is compiled, and then run. At the this "run time", the '$$var' is just a literal, two dollar signs and then 3 letters. when this run time reaches an eval command it then "restarts?" the perl compiler, to compile whatever string is handed to it, this is when the literal '$$var' is considered code. And then there is a run time for that compiled eval string. It runs that compiled code and returns the "last thing".

Re^3: Please help me understand string eval better
by AnomalousMonk (Archbishop) on Jun 13, 2017 at 03:56 UTC
      To clarify, I wasn't looking for help with specific code but rather for a theoretical answer on what behavioural differences to expect when using each of the three string eval variations.

      Basically what I deduced from your answers so far:
      Option 1 and option 2 are exactly the same under any circumstance, they will always produce the same result no matter what $$var and $transf contain.
      Is this understanding correct?

      With regards to option 3 one difference seems to be that $$var will only be replaced by it's value when the eval is invoked. Is there any other behavioural difference when using option 3 instead of option 1?

      P.S: In my application $$var is a string that contains a decimal number (can have leading zeroes and won't necessarily be an integer) which varies at run-time, while $transf contains matematical operations which also vary at run-time and which I want eval to apply to $$var and then return the result.
      For example $$var could be "09" (or it could be "56.7") and $transf could be "/3+6".
      So I case of $$var="09" and $transf="/3+6" I want eval to return 9 (i.e. the result of: 9/3+6).

      I had to switch from using option 1 to option 3 because the occasional leading zeros (which are inevitable) were causing eval to interpret the value of $$var as an octal (which I don't want) but now that I'm using option 3 I'm unsure if I might get other unexpected side effects.
      Basically I'm uncomfortable using code that I don't fully understand, which is why I'm looking for a comprehensive/theoretical explanation of the consequence of using option 3 instead of option 1.

        It looks like your question isn't so much about eval than about magical string-to-number conversion.

        With regards to option 3 one difference seems to be that $$var will only be replaced by it's value when the eval is invoked. Is there any other behavioural difference when using option 3 instead of option 1?

        No, there is no difference. It's all a matter of what eval gets to evaluate.

        $var = '09'; $trans = '/3+5'; eval "$var$trans"; # eval gets '09/3+5' # Illegal octal digit '9' eval $var.$trans; # eval gets '09/3+5' # Illegal octal digit '9' eval '$var'.$trans; # eval gets '$var/3+5' # result: 8

        What happens in the last case? Well, eval evaluates $var in a numerical operation (division), in which case the number slot of the variable is used. Its string value still is 09, but its numerical value is 9.

        use Devel::Peek; $var = '09'; Dump $var; $var + 0; Dump $var; $var / 3; Dump $var; __END__ SV = PV(0x2e352a0) at 0x2e24fc0 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x2e503f0 "09"\0 CUR = 2 LEN = 10 COW_REFCNT = 0 SV = PVIV(0x254b610) at 0x2e24fc0 REFCNT = 1 FLAGS = (IOK,POK,IsCOW,pIOK,pPOK) IV = 9 PV = 0x2e503f0 "09"\0 CUR = 2 LEN = 10 COW_REFCNT = 0 SV = PVNV(0x2ddfc90) at 0x2e24fc0 REFCNT = 1 FLAGS = (IOK,NOK,POK,IsCOW,pIOK,pNOK,pPOK) IV = 9 NV = 9 PV = 0x2e503f0 "09"\0 CUR = 2 LEN = 10 COW_REFCNT = 0

        As you can see, by adding 0 to $var, the integer slot (IV) of the variable is populated with 9. Dividing $var fills the number slot (NV), so the variable is fit for division. The string value (PV) is still 09.

        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'