Короткий ответ на ваш вопрос таков: $filename
интерполируется в вашем первом примере, тогда как во втором примере его нет. Почему ты спрашиваешь? О, парень. Ремень для ухабистой езды.
Во-первых, поймите, для чего нужна запись ${...}
. Есть две причины использовать его: одна - просто отличить имя переменной от окружающего текста; другое - разыменовать значение, возвращаемое BLOCK (кода).
Если содержимое скобок - просто голое слово (с возможными окружающими пробелами), то это просто простое имя переменной. Таким образом, строка "$foo"
и строка "${foo}"
и строка "${ foo }"
все дают одинаковый результат. Это удобно, если вам нужно добавить текст непосредственно после переменной в строке: вместо «$foo.'bar'
» вы можете сказать «1011 *». Обозначения работают и вне интерполирующих строк: вы можете сказать ${foo} = 'bar'
, если хотите.
Но это не то, что делает ваш код. О нет. Вы нацеливаете двуствольное ружье с символической разыменовкой прямо на свои ноги. Вы оцениваете содержимое скобок как код и используете результат как ссылку на переменную. Вы делаете это вдвойне запутанным, помещая весь лот в интерполирующую строку. Давайте не будем вдаваться в подробности концепции разыменования, так как это не главный вопрос. Ключевым моментом является то, что материал в фигурных скобках эффективно проверяется, если это не голое слово.
Теперь, поймите, что когда Perl достигает нотации "$ {" внутри вашей интерполирующей строки, он должен принять решение о том, что он здесь интерполирует: обычное имя переменной или код. Не интерполируя что-либо еще, ищет соответствующий закрывающий квадрат. Если подстрока, разделенная этими скобками, не выглядит как голое слово, то она будет eval'd. Вам все еще нужно избегать двойных кавычек в этой области, потому что любая неэкранированная двойная кавычка будет считаться конечным разделителем для внешней строки, для которой это подмножество, а остаток вашего «блока» будет вне строки.
Имея это в виду, мы можем видеть, что ваш первый пример пробуждается "_<$filename"
, тогда как ваш второй пример пробуждается '_<$filename'
. В этом и заключается разница между интерполирующей строкой и нет: первая заменена на $filename
чем-то, тогда как вторая строго буквальная.
В обоих случаях строка используется для выполнения символической разыменования глобальной скалярной переменной со страшным именем, и вам будет стыдно, если вы ее действительно определили. Чем меньше об этом сказано, тем лучше.
Если вы думаете, что я шучу по поводу того, что содержимое фигурных скобок действительно эффективно, попробуйте этот код.
print "This, ${die qq(oops!\n)}, and this.\n";
Конечно, ключевое отличие между таким строковым кодом и eval()
в том, что eval()
перехватит исключение и установит $ @. Это не так: он просто умирает, как в обычном кодовом блоке.
Это приводит к одному из скрытых трюков Perl. Вы не можете интерполировать вызов метода, например $foo->bar
, но вы можете разыменовать ссылку на массив, который его содержит, например,
print "@{[$foo->bar]}\n";
Итак, ради любви к Богу, не пишите такой код.