Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

why lexical variables can not be interpolated?

by lightoverhead (Pilgrim)
on Oct 21, 2013 at 16:14 UTC ( #1059136=perlquestion: print w/replies, xml ) Need Help??
lightoverhead has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks

When I read perl cook book,I found the following code:

our ($rows, $cols); #if use my ($rows,$cols), it will not work no strict 'refs'; # for ${$1}/g below my $text; ($rows, $cols) = (24, 80); $text = q(I am $rows high and $cols long); # like single quotes! $text =~ s/\$(\w+)/${$1}/g; print $text; #I am 24 high and 80 long

I am wondering why lexical variable (using my) will not work in this case.

Thank you!

Update:

Got the answer, sorry for this silly question.

symbolic reference is interpreted as a string representing the name of a global variable. So if I use symbolic reference as above, it has to refer to a global variable.

By the way, does anyone know if there will be a new version of Perl Cookbook?

Update questions:

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.

Replies are listed 'Best First'.
Re: why lexical variables can not be interpolated?
by davido (Archbishop) on Oct 21, 2013 at 16:35 UTC

    Regarding your "By the way" question... the most accurate answer will come from the OReilly website itself. Currently this is the most recent: Perl Cookbook, 2nd Edition, from 2003.


    Dave

Re: why lexical variables can not be interpolated?
by kennethk (Abbot) on Oct 21, 2013 at 16:46 UTC

    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.

      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.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1059136]
Approved by davido
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (8)
As of 2017-12-15 22:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What programming language do you hate the most?




















    Results (443 votes). Check out past polls.

    Notices?