Почему @@, @!, @и т.д. Не интерполируются в строках?
Во-первых, обратите внимание, что я задаю этот вопрос из любопытства, и я знаю, что использование имен переменных, таких как @@
, вероятно, не очень хорошая идея.
При использовании двухлокальных кавычек (или оператор qq
) скаляры и массивы интерполируются:
$v = 5;
say "$v"; # prints: 5
[email protected] = 6;
say "[email protected]"; # prints: 6
@a = (1,2);
say "@a"; # prints: 1 2
Тем не менее, с именами массивов формы @
+ special char типа @@
, @!
, @,
, @%
, @;
и т.д. массив не интерполируется:
@; = (1,2);
say "@;"; # prints nothing
say @; ; # prints: 1 2
Итак, вот мой вопрос: кто-нибудь знает, почему такие массивы не интерполированы? Документировано ли это где угодно?
Я не мог найти никакой информации или документации об этом. В google (или SO) слишком много статей/сообщений об основах интерполяции, поэтому, возможно, ответ был просто скрыт в одном из них или на 10-й странице результатов.
Если вам интересно, зачем мне нужны имена переменных, например:
-
Флаг -n
(и -p
на этот счет) добавляет точку с запятой ;
в конце кода (я не уверен, что она работает на каждую версию perl, хотя). Поэтому я могу сделать эту программу perl -nE '[email protected],1;say"@a"}{[email protected]'
короче, вместо этого perl -nE '[email protected];,1;say"@;"}{[email protected]'
, потому что последняя ;
конвертировать [email protected]
в [email protected];
. Ну, на самом деле я не могу этого сделать, потому что @;
не интерполируется в двойных кавычках. Это не будет полезно каждый день, конечно, но в некоторых играх в гольф, почему бы и нет!
-
Может быть полезно обфускать некоторый код. (полезно ли обфускация или нет, это еще одна дискуссия!)
Ответы
Ответ 1
К сожалению, я не могу сказать, почему, но это ограничение исходит из кода в 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 году. (Исключение в шаблонах регулярных выражений было добавлено, чтобы сделать работу /[\[email protected]\c_]/
, сначала для интерполяции @-
.)
Существует обход: Поскольку @{
рассматривается как начало переменной массива, синтаксис "@{;}"
работает (но это не помогает вашему коду гольфа, потому что он делает код длиннее).
Ответ 2
Документация Perl говорит, что результат "не является строго предсказуемым".
Ниже, из perldoc perlop
(Perl 5.22.1), относится к интерполяции скаляров. Я предполагаю, что он применим в равной степени к массивам.
Заметим также, что интерполяционный код должен принять решение о где заканчивается интерполированный скаляр. Например, "a $x -> {c}"
действительно означает:
"a " . $x . " -> {c}";
или
"a " . $x -> {c};
В большинстве случаев самый длинный текст, который не включает промежутки между компонентами и которые содержат соответствующие фигурные скобки или кронштейны. поскольку результат может быть определен путем голосования на основе эвристические оценки, результат не является строго предсказуемым. К счастью, он обычно подходит для двусмысленных случаев.
Ответ 3
Некоторые вещи только потому, что "Ларри закодировал это так". Или, как я обычно говорил в классе: "Это работает так, как вы думаете, если вы думаете, как думает Ларри", иногда добавляя "и это моя работа, чтобы научить вас, как думает Ларри".