Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Re: Please help me understand string eval better

by AnomalousMonk (Archbishop)
on Jun 13, 2017 at 02:32 UTC ( [id://1192645]=note: print w/replies, xml ) Need Help??


in reply to Please help me understand string eval better

    eval "$$var$transf"

    eval $$var.$transf

These two expresions are essentially the same.  $$var.$transf is simply an explicit string concatenation that would be done implicitly in a  "$$var$transf" double-quotish interpolation. (Update: The concatenation/interpolation is done at run time, and then the resulting string is eval-ed.)

    eval '$$var'.$transf

This is a bit different. A literal string  '$$var' (the dollar signs are part of the literal string) is explicitly concatenated with the stringization of whatever is in the  $transf scalar. (Update: Again, the concatenation is done at run time and the resulting string is eval-ed.)

Try experimenting with these string expressions — without the eval part until you're sure what's going on!

Update 1: Note that  $$var is the dereference of a reference to a scalar:  $var holds a reference to some other scalar.

Update 2: Some examples:

c:\@Work\Perl\monks>perl -wMstrict -le "my $foo = 'rm '; my $var = \$foo; my $transf = '-R *'; ;; print qq{A: >$$var$transf<}; print 'B: >', $$var.$transf, '<'; print 'C: >', '$$var'.$transf, '<'; " A: >rm -R *< B: >rm -R *< C: >$$var-R *<
Once again, experiment — it's fun and easy!

Update 3:

... what gets done ... at compile time ...
That's the  eval BLOCK form. It's compiled at... well, compile time, and must be syntactically correct. (The  eval EXPR form need not be.) Please see the docs for more info, get back to us with any specific questions.


Give a man a fish:  <%-{-{-{-<

Replies are listed 'Best First'.
Re^2: Please help me understand string eval better
by perltux (Monk) on Jun 13, 2017 at 03:25 UTC
    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.

      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".

        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.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1192645]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-04-23 22:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found