Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
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 imbibing at the Monastery: (7)
As of 2018-07-18 20:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?















    Results (396 votes). Check out past polls.

    Notices?