Dada Dada - 11 months ago 40
Perl Question

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
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
    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
    . 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!)

Answer Source

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).