2010-08-26 71 views
4

Perl被认为是通用编程语言吗?Perl提供的其他语言不支持哪些编译时功能?

Wikipedia

Perl的阅读有关它具有图灵完全语法解析,因为可通过在编译阶段执行的运行时代码的影响。[41]因此,Perl不能由直接的Lex/Yacc词法分析器/解析器组合来分析。相反,解释器实现自己的词法分析器,它与修改过的GNU野牛分析器进行协调,以解决语言中的歧义问题。

通常会说“只有perl可以解析Perl”,这意味着只有Perl解释器(perl)才能解析Perl语言(Perl),但即使这样也不是真的。由于Perl解释器可以在其编译阶段模拟图灵机,因此需要确定停机问题以便在每种情况下完成解析。这是一个长期以来的结果,暂停问题是不可判定的,因此甚至连perl都不能解析Perl。 Perl使得用户可以在自己的编译阶段访问其完整的编程能力。理论纯度方面的成本很高,但实际的不便似乎很少见。

所以,它说,虽然Perl有图灵完整的徽章,它与其他语言不同,因为给了“在自己的编译阶段,以充分发挥其编程能力的用户访问”。那是什么意思? Perl在编译阶段为我提供了哪些编程能力?

+0

社区Wiki? – fredley 2010-08-26 13:39:34

+5

这是一个非主观答案的恰当问题。 – muhmuhten 2010-08-26 13:42:54

+2

这个维基百科条目需要编辑。即使编译完成,编译器也不需要在编译过程中“决定”暂停问题。这是循环逻辑。 – dawg 2010-08-26 13:49:08

回答

6

Perl没有任何功能不会出现在任何其他语言中。 Lisp可以做任何事情(Lisp是示例,在这里)。因此,也许我们可以缩小问题的范围,Perl的功能是什么,使广泛的行为摆动是一件容易的事情。

  • BEGIN块(END块,太。),其期间编译改变行为。所以我可以编写Perl代码来改变要加载的模块的位置。

    即使下面的代码可能有不同的含义。

    use Frobnify; 
    Frobnify->new->initialize; 
    

    ,因为我已经改变了这里Frobnify负载从:

    BEGIN { 
        if ([ localtime ]->[6] == 2) { 
         s|^/var|/var/days/tuesday| foreach @INC; 
        } 
    } 
    

    所以在星期二,我加载/var/days/tuesday/perl/lib/Frobnify.pm

  • Source Filters可以通过编程编辑将执行代码。 (源代码过滤器上的CAVEAT!)(粗略地和大致等同于LISP宏)

  • BEGIN有一些区别是@INC hooks。因为我可以在开始时修改@INC以查看更改加载的内容。我可以在@INC阵列的前面设置一个子程序来加载我想加载的任何东西。挂钩可以接收加载Frobnify的请求,并通过加载Defrobnify.pm来响应该请求。

  • 与此相关的还有Symbol Manipuation。加载Defrobnify.pm后,我可以这样做:

    *Frobnify:: = \*Defrobnify::; 
    

    现在Frobnify->new创建Defrobnify对象!

+0

LISP比Perl更普遍。 – delnan 2010-08-26 13:50:04

+4

@delnan它取决于你的意思是“编译”。 Perl被编译为字节码。 @Axeman:“LISP可以做任何事情”:你是什么意思?任何图灵完全语言都可以在可计算性上做任何事情,但是我还没有看到一种语言不缺少我喜欢的其他语言的特性。 – 2010-08-26 13:52:49

+0

@delnan:Perl总是*编译,所以这是不可能的。我对LISP不是最新的,我的理解是它被解释了。 – Axeman 2010-08-26 14:01:53

1

简单的答案是,BEGIN块提供图灵完备:

BEGIN { 
    my $foo = turing_machine_simulator($program); 
} 

BEGIN块尽快Perl编译看到他们执行。这意味着可以要求编译器执行任意复杂的任务。 Perl可以做什么,它可以在编译阶段完成。

4

子程序原型是一个编译时间功能,或多或少是Perl专用的。 Perl的许多内置函数在其参数(标量,列表,引用,代码块,捕获)上施加了特殊类型的上下文。原型是将某些功能移植到用户定义的子例程的一种方式。

例如,Perl允许您用(&)原型有效地生成新的句法结构。这是在模块中使用像Try::Tinytrycatch关键字添加到语言:

try { 
      die "foo"; 
    } catch { 
      warn "caught error: $_"; # not [email protected] 
    }; 

这工作,因为trycatch被声明为sub try (&;@) { ... }sub name {...}语法相当于BEGIN { *name = sub {...} }这意味着它具有编译时效果。在try的情况下,(&;@)原型告诉编译器,只要它看到标识try,第一个参数必须是裸块,并且在块之后是可选列表。

这只是一个原型的例子,他们能够做很多其他的事情:

$ imposes scalar context on an argument 
& imposes code context on an argument 
@ imposes list context on an argument 
% imposes list context (with an even number of elements) 
* imposes glob context on the argument 
\$ imposes scalar reference context 
\@ imposes array reference context 
    ... for the rest of the sigils 

由于他们的权力(而没有其他语言)的原型可以是混乱和适度最好使用。 (就像Perl的其他高级功能一样)。

+0

此外,名称是一个问题。 C原型与Perl原型完全不同。 – daotoad 2010-08-27 00:06:29