Beefy Boxes and Bandwidth Generously Provided by pair Networks httptech
Perl: the Markov chain saw
 
PerlMonks  

Re: why lexical variables can not be interpolated?

by kennethk (Monsignor)
on Oct 21, 2013 at 16:46 UTC ( #1059141=note: print w/ replies, xml ) Need Help??


in reply to why lexical variables can not be interpolated?

Obligatory documentation reference: Symbolic references in perlref.


#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.


Comment on Re: why lexical variables can not be interpolated?
Re^2: why lexical variables can not be interpolated?
by lightoverhead (Monk) on Oct 21, 2013 at 16:55 UTC

    Thank you for replying to my questions.

    After playing around with this '/e' modifier with s///, I do have a question which I cannot solve now:

    $AGE = 17; $text = 'I am $AGE years old'; # note single quotes $text =~ s/(\$\w+)/$1/eeg; # print I am 17 years old $text =~ s/(\$\w+)/$1 * 2/eegx; #I tried to double the age, but faile +d

    How I can double the age in s/// format for the above code as showed by a similar but different example:

    $text = "I am 17 years old"; $text =~ s/(\d+)/2 * $1/eg; #now I am 34 years old

    Thank you.

      As described in s/PATTERN/REPLACEMENT/msixpodualgcer in perlop,
      e Evaluate the right side as an expression.
      ee Evaluate the right side as a string then eval the result.
      The reason $text =~ s/(\$\w+)/$1/eeg; works is the regular expression stores $AGE (string literal) in $1. For the substitution, $1 is evaluated to return $AGE, and then $AGE is evaluated to return 17. Your second code attempts to multiply the string literal $AGE by 2, not the value of it - you've got your order of operations off. You could accomplish this using an explicit dereference rather than invoking eval twice, like
      $text =~ s/\$(\w+)/$$1 * 2/egx; #I tried to double the age and succee +ded!
      What I've changed:
      1. I used an explicit dereference $$1, which could also be expressed as ${$1}
      2. I changed the pattern so that the sigil is replaced, but is not part of the pattern. This is necessary because $$1 attempts to access the scalar variable named AGE; otherwise it would assume you are looking for a variable with an explicit dollar sign in its name.
      3. I changed the code to eval only once.

      I realize that this is a learning exercise, but for reference if I were going to do this kind of templating, I would use sprintf in something like:

      $AGE = 17; $tmpl = 'I am %s years old'; # note single quotes $text = sprintf $tmpl, $AGE * 2; # print I am 17 years old

      #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

        kennethk

        Thank you for your detailed answers to this question.

        I know if I use a symbolic reference will get this done. But it will not work for lexical scope variable. If, for example, I use:

        my $AGE =17 #instead of $AGE=17

        your solution will fail.

        It seems to me that it's impossible to use /e to solve this situation when variable is lexical scoped.

        Yes, sprintf will work for this case as we know it's a number; but in other cases we may not know if $AGE holds a numeric value.

        Any thoughts?

        Thank you!

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (6)
As of 2014-04-21 06:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (492 votes), past polls