Почему фильтры источника Perl плохие, и когда их использовать?

"Общеизвестно", что исходные фильтры являются плохими и не должны использоваться в производственном коде.

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

  • Почему исходные фильтры плохие?
  • Когда можно использовать фильтр источника?

Ответ 1

Только perl может анализировать Perl (см. этот пример):

@result = (dothis $foo, $bar);

# Which of the following is it equivalent to?
@result = (dothis($foo), $bar);
@result = dothis($foo, $bar);

Такая неоднозначность очень затрудняет запись фильтров источников, которые всегда преуспевают и поступают правильно. Когда все идет не так, отладка неудобна.

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

Я иногда использую Smart::Comments для отладки. Когда я это сделаю, я загружаю модуль в командной строке:

$ perl -MSmart::Comments test.pl

чтобы исключить возможность его включения в производственном коде.

См. также: Perl не может быть проанализирован: формальное доказательство

Ответ 2

Почему исходные фильтры плохие:

  • Ничего, кроме Perl, может анализировать Perl. (Фильтры источника нестабильны.)
  • Когда исходный фильтр ломается, все может произойти. (Они могут вводить тонкие и очень трудно найти ошибки.)
  • Фильтры источника могут разорвать инструменты, которые работают с исходным кодом. (PPI, рефакторинг, статический анализ и т.д.).
  • Исходные фильтры являются взаимоисключающими. (Вы не можете использовать более одного за раз - если вы не психотик).

Когда все будет в порядке:

  • Вы экспериментируете.
  • Вы пишете код.
  • Ваше имя - Дамиан, и вам должно быть разрешено программировать на латинском языке.
  • Вы программируете на Perl 6.

Ответ 3

Мне не нравятся исходные фильтры, потому что вы не можете сказать, какой код будет делать, просто прочитав его. Кроме того, вещи, которые выглядят так, как будто они не исполняются, например комментарии, могут волшебным образом исполняться с фильтром. Вы (или, скорее всего, ваши коллеги) можете удалить то, что, по вашему мнению, не важно и сломать вещи.

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

Ответ 4

Следует отметить, что ключевые слова Devel::Declare (и начиная с Perl 5.11.2, подключаемые ключевые слова) не являются исходными фильтрами и не запускают проблему "только Perl может разобрать Perl". Это связано с тем, что они управляются самим парсером perl, они берут то, что им нужно от ввода, а затем возвращают управление самому парсеру.

Например, когда вы объявляете метод в MooseX::Declare следующим образом:

method frob ($bubble, $bobble does coerce) {
  ... # complicated code
}

Слово "метод" вызывает парсер синтаксиса метода, который использует свою собственную грамматику, чтобы получить имя метода и проанализировать подпись метода (который не является Perl, но это не обязательно), ему просто нужно быть четко определенными). Затем он оставляет perl для анализа тела метода как тела суб. Ничто в любом месте вашего кода, которое не находится между словом "метод" и концом подписи метода, вообще не воспринимается парсером метода, поэтому он не может сломать ваш код, как бы сложно это ни было.

Ответ 5

Проблема, которую я вижу, та же проблема, с которой вы сталкиваетесь с любым макросом C/С++, более сложным, чем определение константы: она снижает вашу способность понимать, что делает код, глядя на него, потому что вы не смотрите на который фактически выполняется.

Ответ 6

В теории исходный фильтр не более опасен, чем любой другой модуль, поскольку вы можете легко написать модуль, который переопределяет встроенные функции или другие конструкции "неожиданными" способами. На практике, однако, довольно сложно написать исходный фильтр таким образом, чтобы вы могли доказать, что он не собирается ошибаться. Я попробовал свои силы при написании исходного фильтра, который реализует операторы подачи perl6 в perl5 (Perl6::Feeds на cpan). Вы можете взглянуть на регулярные выражения, чтобы увидеть акробатику, необходимую для простого определения границ области выражения. В то время как фильтр работает и предоставляет тестовое поле для экспериментов с каналами, я бы не стал использовать его в производственной среде без большого количества часов тестирования.

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

В целом, это действительно зависит от используемого фильтра и от того, насколько широка область действия, с которой он пытается сопоставлять. Если это что-то простое, как макрос c, то его "возможно" нормально, но если его что-то осложняет, то его вызов. Я лично не могу дождаться, когда поиграю с макросистемой perl6. Наконец lisp не будет иметь ничего на perl: -)

Ответ 7

Здесь есть хороший пример, который показывает, в чем могут возникнуть проблемы с фильтрами источников. http://shadow.cat/blog/matt-s-trout/show-us-the-whole-code/

Они использовали модуль под названием Switch, который основан на фильтрах источника. И из-за этого они не смогли найти источник сообщения об ошибке в течение нескольких дней.