Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Perl evaluate code in ${...} during string interpolation?

Why does the following snippet work at all? And what evil might be possible using this? But seriously, is there any reason, the code in ${} gets evaluated at all and then used as scalar reference?

use strict;
no strict 'refs';

our $message = "Hello world!";
print "${ lc 'MESSAGE' }\n";
like image 873
willert Avatar asked Feb 25 '10 09:02

willert


People also ask

What is interpolation in string in Perl?

Interpolation in Perl refers to the process where the respective values replace the variable names. It is commonly used inside double-quoted strings.

Can we use expressions Inside string interpolation?

String interpolation is a technique that enables you to insert expression values into literal strings.

Does Perl allow variable interpolation?

This page shows how variable interpolation works in Perl. Interpolation, meaning "introducing or inserting something", is the name given to replacing a variable with the value of that variable.


1 Answers

We explain this in depth in Intermediate Perl.

The general syntax for variable lookups is:

 SIGIL  BLOCK  INDEXY-THING

For a simple scalar that looks like:

 print $   { foo };

You have probably seen this when you need to separate a variable name from things surrounding it:

 print "abc${foo}def\n";

If you just have a Perl identifier in the block and no surrounding mess, you can leave off the braces, which is the common case:

 print $foo;

However, this is the same thing for dereferencing a reference:

 SIGIL  BLOCK-RETURNING-REFERENCE  INDEXY-THINGS

If the thing that you get in the block is a reference, Perl tries to dereference it like you asked it too:

 my $ref = \ '12345';
 print $     { $ref };

That's a real block though, and not just sugar. You can have as many statements as you like in there:

 print $     { my $ref = \ '1234'; $ref };

Now you're not just specifying a Perl identifier, so Perl doesn't assume that you're giving it an identifier and it executes code and uses the result as a reference. Consider the difference between these almost identical say statements:

    use 5.010;
our $foo = "I'm the scalar";

sub foo { \ "I'm the sub" }

say ${foo};
say ${foo;};

In that second say Perl sees the semi-colon, realizes it's not an identifier, interprets the code inside the braces as text, and returns the result. Since the result is a reference, it uses the ${...} to dereference it. It doesn't matter where you do this, so that you do it inside a double-quoted string is not special.

Also, notice the our there. That's important now that you're going to consider something a bit more tricky:

    use 5.010;
our $foo = "I'm the scalar";

sub foo { \ "I'm the sub" }
sub baz { 'foo' }

say ${foo};
say ${foo;};
say ${baz;};

Perl intreprets that last say as code and sees the result is not a reference; it's the simple string foo. Perl sees that it's not a reference but it's now in a dereferencing context so it does a symbolic reference (as Greg Bacon describes). Since symbolic references work with variables in the symbol table, that $foo had to be a package variable.

Since it's easy to mess this up, strict has a handy check for it. However, when you turn it off, don't be surprised when it bites you. :)

like image 66
brian d foy Avatar answered Oct 21 '22 23:10

brian d foy