为什么Perl源过滤器坏了,什么时候可以使用它们?

时间:2009-11-23 20:50:38

标签: perl source-filter

“常识”是source filters不好,不应在生产代码中使用。

在回答a similar, but more specific question时,我找不到任何好的参考资料,清楚地解释了为什么过滤器坏了以及什么时候可以安全使用。我认为现在是时候创建一个。

  1. 为什么源过滤器不好?
  2. 什么时候可以使用源过滤器?

7 个答案:

答案 0 :(得分:23)

为什么源过滤器不好:

  1. 除了perl之外什么都不能解析Perl。 (源过滤器很脆弱。)
  2. 当源过滤器破坏时,几乎任何事情都可能发生。 (他们可以引入微妙且非常难以发现的错误。)
  3. 源过滤器可以破坏使用源代码的工具。 (PPI,重构,静态分析等)
  4. 源过滤器是互斥的。 (你不能一次使用多个 - 除非你是精神病患者)。
  5. 当他们没事的时候:

    1. 你正在试验。
    2. 你正在写丢弃代码。
    3. 你的名字是达米安,你必须才能进入拉丁语。
    4. 您正在使用Perl 6进行编程。

答案 1 :(得分:19)

只有perl可以解析Perl(请参阅this example):

@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 Cannot Be Parsed: A Formal Proof

答案 2 :(得分:10)

我不喜欢源过滤器,因为你无法通过阅读来判断代码是做什么的。此外,看起来像它们不可执行的东西,例如注释,可能会神奇地使用过滤器执行。你(或者更可能是你的同事)可以删除你认为不重要的东西并破坏事物。

话虽如此,如果您要实现自己想要转换为Perl的小语言,源过滤器可能是正确的工具。但是,不要称之为Perl。 :)

答案 3 :(得分:6)

值得一提的是Devel::Declare关键字(从Perl 5.11.2开始,可插入的关键字)不是源过滤器,并且不会与“只有perl可以解析Perl”问题相冲突。这是因为它们由perl解析器本身运行,它们从输入中获取所需的内容,然后将控制权返回给同一个解析器。

例如,当你在MooseX::Declare中声明一个方法时,这样:

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

单词“method”调用方法关键字解析器,它使用自己的语法来获取方法名称并解析方法签名(不是Perl,但它不需要 - 它只需要定义明确)。然后它离开perl来解析方法体作为sub的主体。代码中任何地方的任何地方不是在单词“method”和方法签名的结尾之间根本不会被方法解析器看到,所以它不会破坏你的代码,无论你多么狡猾。

答案 4 :(得分:3)

我看到的问题是你遇到的任何C / C ++宏都比定义一个常量更复杂:它会降低你通过查看代码来理解代码的能力,因为你没有看到它实际执行的代码。

答案 5 :(得分:2)

理论上,源过滤器并不比任何其他模块更危险,因为您可以轻松编写一个以“意外”方式重新定义内置函数或其他构造的模块。然而,在实践中,编写源过滤器很难以证明它不会出错。我尝试编写一个源过滤器,在perl5中实现perl6 feed操作符(cpan上为Perl6::Feeds)。您可以查看正则表达式,以查看简单地找出表达式范围边界所需的杂技。虽然过滤器工作,并提供试验台来试验饲料,但我不会考虑在没有多少小时测试的情况下在生产环境中使用它。

Filter :: Simple当然可以通过处理“解析引用结构的血腥细节”而派上用场,所以我会对任何不能从那里启动的源过滤器保持警惕。

总之,它实际上取决于您使用的过滤器,以及它尝试匹配的范围有多宽。如果它像c宏一样简单,那么它的“可能”就好了,但是如果它的某些东西很复杂,那么它就是一个判断调用。我个人迫不及待想玩perl6的宏系统。最后lisp在perl上没有任何东西: - )

答案 6 :(得分:1)

这里有一个很好的例子,说明了使用源过滤器可以解决的问题。 http://shadow.cat/blog/matt-s-trout/show-us-the-whole-code/

他们使用了一个名为Switch的模块,该模块基于源过滤器。正因为如此,他们几天都找不到错误信息的来源。