Why are @@, @!, @, etc. not interpolated in strings?

First, please note that I ask this question out of curiosity, and I'm aware that using variable names like @@ is probably not a good idea.

When using doubles quotes (or qq operator), scalars and arrays are interpolated :

$v = 5;
say "$v"; # prints: 5
$@ = 6;
say "$@"; # prints: 6
@a = (1,2);
say "@a"; # prints: 1 2

Yet, with array names of the form @+special char like @@, @!, @,, @%, @; etc, the array isn't interpolated :

@; = (1,2);
say "@;"; # prints nothing
say @; ; # prints: 1 2

So here is my question : does anyone knows why such arrays aren't interpolated? Is it documented anywhere?

I couldn't find any information or documentation about that. There are too many articles/posts on google (or SO) about the basics of interpolation, so maybe the answer was just hidden in one of them, or at the 10th page of results..

If you wonder why I could need variable names like those :

  • The -n (and -p for that matter) flag adds a semicolon ; at the end of the code (I'm not sure it works on every version of perl though). So I can make this program perl -nE 'push@a,1;say"@a"}{say@a' shorter by doing instead perl -nE 'push@;,1;say"@;"}{say@', because that last ; convert say@ to say@;. Well, actually I can't do that because @; isn't interpolated in double quotes. It won't be useful every day of course, but in some golfing challenges, why not!

  • It can be useful to obfuscate some code. (whether obfuscation is useful or not is another debate!)

Answers


Unfortunately I can't tell you why, but this restriction comes from code in toke.c that goes back to perl 5.000 (1994!). My best guess is that it's because Perl doesn't use any built-in array punctuation variables (except for @- and @+, added in 5.6 (2000)).

The code in S_scan_const only interprets @ as the start of an array if the following character is

  • a word character (e.g. @x, @_, @1), or
  • a : (e.g. @::foo), or
  • a ' (e.g. @'foo (this is the old syntax for ::)), or
  • a { (e.g. @{foo}), or
  • a $ (e.g. @$foo), or
  • a + or - (the arrays @+ and @-), but not in regexes.

As you can see, the only punctuation arrays that are supported are @- and @+, and even then not inside a regex. Initially no punctuation arrays were supported; @- and @+ were special-cased in 2000. (The exception in regex patterns was added to make /[\c@-\c_]/ work; it used to interpolate @- first.)

There is a workaround: Because @{ is treated as the start of an array variable, the syntax "@{;}" works (but that doesn't help your golf code because it makes the code longer).


Perl's documentation says that the result is "not strictly predictable".

The following, from perldoc perlop (Perl 5.22.1), refers to interpolation of scalars. I presume it applies equally to arrays.

Note also that the interpolation code needs to make a decision on where the interpolated scalar ends. For instance, whether "a $x -> {c}" really means:

"a " . $x . " -> {c}";

or:

"a " . $x -> {c};

Most of the time, the longest possible text that does not include spaces between components and which contains matching braces or brackets. because the outcome may be determined by voting based on heuristic estimators, the result is not strictly predictable. Fortunately, it's usually correct for ambiguous cases.


Some things are just because "Larry coded it that way". Or as I used to say in class, "It works the way you think, provided you think like Larry thinks", sometimes adding "and it's my job to teach you how Larry thinks."


Need Your Help

What are "Microsoft Office Protocol Discovery" and "OfficeLiveConnector" and why do they access invalid URLs?

ms-office

I monitor 404s on my sites closely which helps me detect broken links and hacking attempts but I've recently been getting log spam from browsers with these strings in the User Agent. They seem to be

Nokogiri installation fails -libxml2 is missing

ruby-on-rails ruby rubygems

I always worked my way around Nokogiri installation issues by following the documentation in the "Installing Nokogiri" tutorial.