Подтвердить что ты не робот

Существуют ли какие-либо недостатки для интерполяции в Perl?

Я только начинаю с Perl (буквально сегодня), и я читаю бесплатную онлайн-версию Начиная с Perl. Раньше в книге упоминалось, что двойные кавычки будут интерполированы. Тем не менее, в каждом примере с использованием функции печати (до сих пор... я около страницы 66) автор передает скалярные переменные в качестве параметра списка. Возможно, я прыгаю с пистолетом, и это будет объяснено позже, но есть ли какая-то причина выбора метода A по методу B?

Метод A:

$myVar = "value";
print "Current value is ", $myVar, "\n";

Метод B:

$myVar = "value";
print "Current value is $myVar\n";

На мой взгляд, метод B более удобен. Есть ли предпочтительный способ в сообществе? Или, может быть, некоторые скрытые хотча, которые делают один метод более безопасным для использования над другим и т.д.?

ТИА

4b9b3361

Ответ 1

В простом примере, таком как это, нет.. но рассмотрим, было ли $myVar на самом деле чем-то более сложным, например глубокое разыменование хеш-ссылки или вызов метода. Некоторые вещи интерполируются внутри строк (большинство ссылок на объекты), но вызовы методов не делают. Кроме того, массивы выполняют разные вещи при распечатке напрямую или через интерполяцию в строку.

PS. Добро пожаловать в Perl; пожалуйста, наслаждайтесь путешествием!:)

Ответ 2

Там определенно скрыты gotchas - perl будет иметь дело с простыми именами переменных, а выражения типа

"$array[$subscript]"

и

"$hashref->{key}"

без проблем. Однако, поскольку ваши выражения становятся все более сложными, в конечном итоге perl не сможет определить, где ваше выражение останавливается, а остальная часть вашей строки начинается.

В этой статье представлено множество подробностей Переменная интерполяция в двуконусных строках (изначально здесь, но сейчас)

Ответ 3

Там ' gotcha:

$owner = "John";
$item = "motorcycle".
print "This is $owner $item.\n";  # Oops, parsed as $owner::s

но вышеприведенное может быть безопасно записано как

print "This is ${owner} $item.\n";

Ответ 4

Есть несколько вещей, которые нужно учитывать при интерполяции, хотя, как только вы узнаете о них, вы вряд ли когда-либо делаете их по ошибке.

Помещение имени переменной рядом с допустимым текстом идентификатора. Perl находит самое длинное допустимое имя переменной и не имеет значения, было ли оно определено ранее. Вы можете указать часть имени переменной с фигурными выражениями:

  my $p = 'p';
  print "Mind your $ps and qs\n";  # $ps, not $p

  print "Mind your ${p}s and qs";  # now its $p

Теперь, в этом примере, я забыл апостроф. Если я его добавлю, у меня есть другая проблема, поскольку апостроф раньше был разделителем пакетов из старых дней, и он все еще работает. Скобки тоже работают:

  my $p = 'p';
  print "Mind your $p and q's\n";  # $p::s, not $p

  print "Mind your ${p} and q's";  # now its $p

Perl также может интерполировать обращения отдельных элементов к хэшам и массивам, поэтому размещение указателей рядом с именем переменной может сделать то, что вы не хотите:

 print "The values are $string[$foo]\n";  That the element at index $foo
 print "The values are $string{$foo}\n";  That the value for the key $foo

Если вам нужен адрес электронной почты в строке, вы можете забыть, что Perl интерполирует массивы. Perl использовал для того, чтобы сделать фатальную ошибку, если вы не избежали @:

 print "Send me mail at [email protected]\n";  # interpolates @example

 print "Send me mail at joe\@example.com\n";

Поскольку Perl использует обратную косую черту для выхода из некоторых символов, вам нужно удвоить их, если вы хотите получить буквальный текст:

 print "C:\real\tools\for\new\work";      # not what you might expect

 print "C:\\real\\tools\\for\\new\\work"; # kinda ugly, but that life
 print "C:/real/tools/for/new/work";      # Windows still understands this

Несмотря на эти незначительные ошибки, я очень скучаю по легкости, с которой я могу построить строки в Perl, если мне нужно использовать другой язык.

Ответ 5

Метод A должен быть:

$myVar = "value";
print 'Current value is ', $myVar, "\n";

Когда вы произвольно указываете строку, Perl не утруждает себя чтением всего, что ищет вещи для интерполяции, поэтому, если у вас длинная строка, которая не нуждается в интерполяции, возможно, быстрее использовать одинарные кавычки и добавить динамические части, как указано выше.

Однако это микро-оптимизация, которая на самом деле не имеет большого значения.

Другим случаем использования метода А является строка, в которой содержатся escape-символы, которые вы не хотите беспокоить:

$myVar = 12000;
print 'Conversion from $US to $CND: ', $myVar,\n";

В этом случае вы не хотите, чтобы Perl искал переменные $US и $CND, вы просто хотите, чтобы строка имела знак доллара в нем.

В конце концов, это в основном вопрос стиля. Обычно я стараюсь избегать строк с двойными кавычками, если они мне не нужны.

Ответ 6

так как мы говорим об интерполяции gotchas, стоит упомянуть, что если вы используете одиночные кавычки, чтобы избежать интерполяции, вам все равно нужно избежать конечной косой черты:

'c:\files\'  #parse error
'c:\files\\' #correct

это потому, что последний символ первой строки выглядит как экранированная одиночная кавычка, а не ограничитель строки. также экранированная косая черта будет преобразована в одну косую черту в одинарных кавычках

Ответ 7

Если вы достигли Perl, то вы ищете быстрый способ добиться успеха. Кроме того, вам предлагается сделать это так, как это наиболее похоже на ваш образ мыслей (отсюда и девиз Perl: TMTOWTDI, там больше, чем один способ сделать это). Поэтому: в зависимости от того, что вам легче писать, каким бы способом вы, скорее всего, не поняли, когда вернетесь к коду позже, так вам следует делать это (все остальное, например, дать предполагаемый результат, быть равным).

Если вы обеспокоены "безопасностью", как вы предлагаете, узнайте о tainting, который помогает защитить вас от потенциально вредных данных из внешнего мира.

Ответ 8

(Вероятно, это должна быть вики сообщества.)

Единственная очевидная проблема, которая приходит мне на ум, - это интерполяция массивов. Сравнить

print @arr, "\n";

с

print "@arr\n";

Кроме того, иногда сложное разыменование не очень хорошо работает с интерполяцией, но это редкость.

Ответ 9

Как аутсайдер Perl, который не знаком с любыми редакторами, зависящими от perl, и их полномочиями по подсчету, я голосую за использование одинарных кавычек, когда это возможно. Это упрощает читателю, что эта строка не содержит ничего, что будет интерполировано каким-либо образом.

Ответ 10

Интерполяция - это большое упрощение и экономия времени. Но можно зайти слишком далеко.

Вы можете сделать некоторые причудливые вещи с интерполяцией, если хотите.

@foo = 0..10;
print "$foo[2*3]"; # prints 6

И для захватывающей произвольной интерполяции вы можете использовать эту мерзость:

print "@{[ some_function_call('in list context') ]}";

Если вы действительно хотите сделать интерполированные вызовы функций, для этого есть модуль. Проверьте Interpolation. Это позволяет вам делать такие вещи:

use Interpolation;
print "I like $eval{ what_I_like() };

sub what_like_like {
    return 'pie';
}

И многое, многое другое.

Для фона на этом модуле см. Identity.pm: Очень смешной модуль и Interpolation.