为什么@@,@!,@等没有插入字符串?

Dad*_*ada 23 perl

首先,请注意我出于好奇而问这个问题,我知道使用变量名称@@可能不是一个好主意.

使用双精度引号(或qq运算符)时,会插入标量和数组:

$v = 5;
say "$v"; # prints: 5
$@ = 6;
say "$@"; # prints: 6
@a = (1,2);
say "@a"; # prints: 1 2
Run Code Online (Sandbox Code Playgroud)

然而,与阵列形式的名称@+ 特殊字符@@,@!,@,,@%,@;等,该阵列是不是插值.

@; = (1,2);
say "@;"; # prints nothing
say @; ; # prints: 1 2
Run Code Online (Sandbox Code Playgroud)

所以这是我的问题:有谁知道为什么这些数组没有插值?是否记录在任何地方?

我找不到任何关于此的信息或文档.谷歌(或SO)上关于插值基础知识的文章/帖子太多了,所以答案可能只隐藏在其中一个,或者在结果的第10页.

如果你想知道为什么我需要这样的变量名称:

  • -n(和-p为此事)标志增加了一个分号;在代码的最后(我不知道它的工作原理上的perl的每个版本虽然).所以我可以perl -nE 'push@a,1;say"@a"}{say@a'通过改为缩短 这个程序perl -nE 'push@;,1;say"@;"}{say@',因为最后;转换say@say@;.好吧,实际上我做不到,因为@;没有用双引号插值.当然,它每天都没有用,但在一些高尔夫挑战中,为什么不呢!

  • 模糊一些代码可能很有用.(混淆是否有用是另一个争论!)

mel*_*ene 17

不幸的是我无法告诉你为什么,但这个限制来自于代码toke.c,可以追溯到perl 5.000(1994!).我最好的猜测是,因为Perl不使用任何内置的数组标点符号变量(除了@-@+(在5.6(2000)中添加).

如果以下字符是,则代码S_scan_const仅解释@为数组的开头

  • 字字符(例如@x,@_,@1),或
  • a :(例如@::foo),或
  • a '(例如@'foo(这是旧的语法::)),或
  • a {(例如@{foo}),或
  • a $(例如@$foo),或
  • a +-(数组@+@-),但不在正则表达式中.

正如你所看到的,所支持的唯一的标点符号阵列@-@+,而且当时没有一个正则表达式中.最初没有支持标点阵列; @-并且@+在2000年是特殊的.(正则表达式模式的例外被添加到/[\c@-\c_]/工作中;它用于首先插入@-.)

有一种解决方法:因为@{被视为数组变量的开头,所以语法"@{;}"有效(但这对您的高尔夫代码没有帮助,因为它会使代码更长).

  • @zdim`说@@`是有效的,因为当lexer在双引号字符串中处理时,它们的处理方式不同.代码melpomene指的是[这里](https://github.com/Perl/perl5/blob/blead/toke.c#L3220).正如您所看到的,在执行字符串插值时,在@`之后仅查找某些字符是硬编码的. (2认同)

Kei*_*son 6

Perl的文档说,结果"不是严格可预测的".

以下,来自perldoc perlop(Perl 5.22.1),指的是标量的插值.我认为它同样适用于数组.

还要注意,插值代码需要确定插值标量的结束位置.例如,是否 "a $x -> {c}"真的意味着:

"a " . $x . " -> {c}";
Run Code Online (Sandbox Code Playgroud)

要么:

"a " . $x -> {c};
Run Code Online (Sandbox Code Playgroud)

大多数情况下,最长的文本不包括组件之间的空格,并且包含匹配的大括号或括号.因为结果可以通过基于启发式估计器的投票来确定,所以结果不是严格可预测的.幸运的是,对于模棱两可的案例,它通常是正确的.