Perl 提供了哪些其他语言没有的编译时功能?
Perl 被视为通用编程语言吗?
Perl 具有图灵完备语法,因为解析可能会受到编译阶段执行的运行时代码的影响。[41]因此,Perl 不能由直接的 Lex/Yacc 词法分析器/解析器组合来解析。相反,解释器实现了自己的词法分析器,它与修改后的 GNU bison 解析器协调来解决语言中的歧义。
人们常说“只有 Perl 可以解析 Perl”,意思是只有 Perl 解释器 (perl) 才能解析 Perl 语言 (Perl),但即使如此,一般来说也是不正确的。因为 Perl 解释器可以在编译阶段模拟图灵机,所以它需要决定停止问题以便在每种情况下完成解析。停机问题是不可判定的,这是一个长期存在的结果,因此即使是 perl 也不能总是解析 Perl。 Perl 做出了不同寻常的选择,让用户在自己的编译阶段访问其完整的编程能力。理论上的纯度成本很高,但实际带来的不便似乎很少见。
因此,它说虽然 Perl 拥有图灵完备徽章,但它与其他语言不同,因为“用户可以在自己的编译阶段访问其完整的编程能力”。这意味着什么? Perl 在编译阶段为我提供了哪些其他人没有提供的编程能力?
Is Perl considered a general purpose programming language?
Reading about it on Wikipedia
Perl has a Turing-complete grammar because parsing can be affected by run-time code executed during the compile phase.[41] Therefore, Perl cannot be parsed by a straight Lex/Yacc lexer/parser combination. Instead, the interpreter implements its own lexer, which coordinates with a modified GNU bison parser to resolve ambiguities in the language.
It is often said that "Only perl can parse Perl," meaning that only the Perl interpreter (perl) can parse the Perl language (Perl), but even this is not, in general, true. Because the Perl interpreter can simulate a Turing machine during its compile phase, it would need to decide the Halting Problem in order to complete parsing in every case. It's a long-standing result that the Halting Problem is undecidable, and therefore not even perl can always parse Perl. Perl makes the unusual choice of giving the user access to its full programming power in its own compile phase. The cost in terms of theoretical purity is high, but practical inconvenience seems to be rare.
So, it says that though Perl has the Turing complete badge, it is different from other languages because gives "the user access to its full programming power in its own compile phase". What does that mean? What programming power does Perl provide me at compiling phase that others don't?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Perl 的所有功能都出现在任何其他语言中。 Lisp 可以做任何事情(Lisp 是一个例子,这里。)。因此,也许我们可以将问题缩小到 Perl 的哪些特性使得广泛的行为波动变得很容易。
开始
块(也是 END 块)会改变编译期间的行为。因此我可以编写 Perl 代码来更改要加载的模块的位置。
即使下面的代码也可能有不同的含义。
因为我可以更改 Frobnify 的加载位置:
<前><代码>开始{
if ( [当地时间]->[6] == 2 ) {
s|^/var|/var/days/tuesday| foreach @INC;
}
}
所以在星期二,我加载
/var/days/tuesday/perl/lib/Frobnify.pm
源过滤器 可以以编程方式编辑将要执行的代码。 (注意源过滤器!)(粗略地大致相当于 LISP 宏)
与
BEGIN
块一起的是@INC
挂钩。因为我可以在开始时修改@INC
来查看加载内容的变化。我可以在 @INC 数组的前面设置一个子例程来加载我想要加载的任何内容。该挂钩可以接收加载Frobnify
的请求,并通过加载Defrobnify.pm
来响应该请求。与此相伴的是符号操作。加载
Defrobnify.pm
后,我可以执行以下操作:现在,
Frobnify->new
创建一个Defrobnify
对象!There are no features of Perl that do not appear in any other language. Lisp can do anything (Lisp is an example, here.). So perhaps we can narrow the question down to what are the features of Perl that make wide behavior swings an easy thing to do.
BEGIN
blocks (END blocks, too.) which alter the behavior during compile. So I can write Perl code that changes the location of modules to be loaded.Even the following code might have a different meaning.
Because I could have changed where Frobnify loads from:
So on Tuesdays, I load
/var/days/tuesday/perl/lib/Frobnify.pm
Source Filters can programmatically edit the code that will perform. (CAVEAT on source filters!) (crudely and roughly equivalent to LISP macros)
Somewhat along with
BEGIN
blocks are@INC
hooks. As I can modify@INC
at the beginning to see change what gets loaded. I can set a subroutine at the front of the@INC
array to load anything I want to load. The hook can receive a request to loadFrobnify
and respond to it by loadingDefrobnify.pm
.Somewhat along with this is Symbol Manipuation. After loading
Defrobnify.pm
, I can do this:Now
Frobnify->new
creates aDefrobnify
object!子例程原型是一种编译时功能,或多或少是 Perl 独有的。许多 Perl 的内置函数在其参数上强加了特殊类型的上下文(标量、列表、引用、代码块、捕获)。原型是将某些功能移植到用户定义的子例程的一种方法。
例如,Perl 允许您使用
(&)
原型有效地生成新的语法结构。这用于 Try::Tiny 等模块中添加try< /code> 和
catch
语言关键字:这是有效的,因为
try
和catch
被声明为sub try (&;@ ) { ... }
。sub name {...}
语法相当于BEGIN { *name = sub {...} }
,这意味着它具有编译时效果。在try
的情况下,(&@)
原型告诉编译器,任何时候它看到标识符try
,第一个参数必须是一个裸块,块后面是一个可选列表。这只是原型的一个示例,它们还可以做许多其他事情:
由于它们的强大功能(并且在其他语言中不存在),原型可能会令人困惑,最好适度使用。 (就像 Perl 的所有其他高级功能一样)。
Subroutine prototypes are a compile time feature that is more or less exclusive to Perl. Many of Perl's builtin functions impose special types of context on their arguments (scalar, list, reference, code-block, capture). Prototypes are a way of porting some of that functionality over to user defined subroutines.
For example, Perl allows you to effectively generate new syntactic constructs with the
(&)
prototype. This is used in modules like Try::Tiny to addtry
andcatch
keywords to the language:This works because
try
andcatch
are declared assub try (&;@) { ... }
. Thesub name {...}
syntax is equivalent toBEGIN { *name = sub {...} }
which means it has a compile time effect. In the case oftry
, the(&;@)
prototype tells the compiler that any time it sees the identifiertry
, the first argument must be a bare block, and following the block is an optional list.This is just one example of prototypes, and they are able to do many other things:
Due to their power (and absence in other languages) prototypes can be confusing and are best used in moderation. (like every other advanced feature of Perl).
简单的答案是
BEGIN
块提供图灵完备性:BEGIN
块在 Perl 编译器看到它们后立即执行。这意味着可以要求编译器执行任意复杂度的任务。 Perl 能做的任何事情,它都可以在编译阶段完成。The simple answer is that
BEGIN
blocks provide Turing-completeness:BEGIN
blocks are executed as soon as the perl compiler sees them. This means that the compiler can be asked to do tasks of arbitrary complexity. Anything Perl can do, it can do during its compilation phase.