Там какие-либо недостатки к интерполяции в Perl?

Brainfuck: с поддержкой bignum!

Принимает в качестве входных данных неотрицательное целое число, за которым следует символ новой строки, и выводит соответствующий факториал, за которым следует символ новой строки.

>>>>,----------[>>>>,----------]>>>>++<<<<<<<<[>++++++[<----
-->-]<-<<<<]>>>>[[>>+<<-]>>[<<+>+>-]<->+<[>>>>+<<<-<[-]]>[-]
>>]>[-<<<<<[<<<<]>>>>[[>>+<<-]>>[<<+>+>-]>>]>>>>[-[>+<-]+>>>
>]<<<<[<<<<]<<<<[<<<<]>>>>>[>>>[>>>>]>>>>[>>>>]<<<<[[>>>>+<<
<<-]<<<<]>>>>+<<<<<<<[<<<<]>>>>-[>>>[>>>>]>>>>[>>>>]<<<<[>>>
+<<<-]>>>[<<<+>>+>-]<-[>>+<<[-]]<<[<<<<]>>>>[>[>+<-]>[<<+>+>
-]<<[>>>+<<<-]>>>[<<<+>>+>-]<->+++++++++[-<[-[>>>>+<<<<-]]>>
>>[<<<<+>>>>-]<<<]<[>>+<<<<[-]>>[<<+>>-]]>>]<<<<[<<<<]<<<[<<
<<]>>>>-]>>>>]>>>[>[-]>>>]<<<<[>>+<<-]>>[<<+>+>-]<->+<[>-<[-
]]>[-<<-<<<<[>>+<<-]>>[<<+>+>-]<->+<[>-<[-]]>]<<[<<<<]<<<<-[
>>+<<-]>>[<<+>+>-]+<[>-<[-]]>[-<<++++++++++<<<<-[>>+<<-]>>[<
<+>+>-]+<[>-<[-]]>]<<[<<<<]>>>>[[>>+<<-]>>[<<+>+>-]<->+<[>>>
>+<<<-<[-]]>[-]>>]>]>>>[>>>>]<<<<[>+++++++[<+++++++>-]<--.<<
<<]++++++++++.

В отличие от ответа brainf * ck, опубликованного ранее, этот не переполняет любые области памяти. (Эта реализация помещает n! В одну ячейку памяти, фактически ограничивая ее до n менее 6 в соответствии со стандартными правилами bf.) Эта программа выведет n! для любого значения n, ограниченного только временем и памятью (или реализацией bf). Например, используя компилятор Урбана Мюллера на моей машине, для вычисления 1000 потребуется 12 секунд! Я думаю, что это довольно хорошо, учитывая, что программа может двигаться только влево / вправо и увеличиваться / уменьшаться на единицу.

Верьте или нет, это первая программа, написанная мной для BF; На это ушло около 10 часов, которые в основном были потрачены на отладку. К сожалению, я позже узнал, что Дэниел Б. Кристофани написал факториальный генератор , который просто выводит все более крупные факториалы, никогда не заканчивая:

>++++++++++>>>+>+[>>>+[-[<<<<<[+<<<<<]>>[[-]>[<<+>+>-]<[>+<-
]<[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>[-]>>>>+>+<
<<<<<-[>+<-]]]]]]]]]]]>[<+>-]+>>>>>]<<<<<[<<<<<]>>>>>>>[>>>>
>]++[-<<<<<]>>>>>>-]+>>>>>]<[>++<-]<<<<[<[>+<-]<<<<]>>[->[-]
++++++[<++++++++>-]>>>>]<<<<<[<[>+>+<<-]>.<<<<<]>.>>>>]

Его программа намного короче, но он практически профессиональный гольфист.

12
задан 2 revs 17 November 2009 в 19:24
поделиться

10 ответов

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

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

12
ответ дан 2 December 2019 в 02:58
поделиться

Там ' gotcha:

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

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

print "This is ${owner}'s $item.\n";
12
ответ дан 2 December 2019 в 02:58
поделиться

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

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

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

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

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

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

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

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

4
ответ дан 2 December 2019 в 02:58
поделиться

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

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

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

3
ответ дан 2 December 2019 в 02:58
поделиться

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

Добавление имени переменной рядом с допустимым текстом идентификатора. 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's and q's\n";  # $p::s, not $p

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

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

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

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

 print "Send me mail at joe@example.com\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's life
 print "C:/real/tools/for/new/work";      # Windows still understands this

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

12
ответ дан 2 December 2019 в 02:58
поделиться

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

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

2
ответ дан 2 December 2019 в 02:58
поделиться

(Вероятно, это вики сообщества.)

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

print @arr, "\n";

с

print "@arr\n";

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

1
ответ дан 2 December 2019 в 02:58
поделиться

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

0
ответ дан 2 December 2019 в 02:58
поделиться

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

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

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

А для увлекательной произвольной интерполяции вы можете использовать эту мерзость:

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

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

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

sub what_like_like {
    return 'pie';
}

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

Информацию об этом модуле можно найти в Identity.pm: очень забавный модуль и Интерполяция .

0
ответ дан 2 December 2019 в 02:58
поделиться

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

"$array[$subscript]"

и

"$hashref->{key}"

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

В этой статье много кровавых деталей. Интерполяция переменных в Double -Котированные строки (первоначально здесь ,

14
ответ дан 2 December 2019 в 02:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: