你没有提供明确的问题,因此无法得到明确的答案。
Perl始终处于两种状态之一:编译或执行。这就是为什么会出现“在编译时”和“在运行时”的讨论。通常情况下,您会得到一个编译阶段,然后是一个执行阶段,但不一定是这样。
这两个阶段也可以交替进行。 eval STRING
是解释器调用编译器的一种方式(do FILE
和require
也是如此)。BEGIN
块是编译器调用解释器的一种方式(use
和no
也是如此)。
当您运行perl -c
时,省略了运行时阶段。有各种方法可以跳过编译时阶段,但它们中没有一种特别方便或普遍。 Apache的mod_perl
只编译脚本一次,但执行多次。如果您使用Byteloader,则可以做到同样的效果。等等。
关于Perl是编译还是解释语言的正确答案是是。
这要看你所谓的编译语言是什么意思。也许这就是为什么谷歌搜索没有明确回答你问题的原因。
一个观点是,编译意味着从源代码描述到另一个描述的编译,即代码生成。
如果我们接受这些前提条件,那么Perl 6可以被编译,而Perl 5和更早版本则是解释型语言。
Perl 6被专门编译成Parrot字节码。 因此,Perl 6是一种正确的编译语言,就像Java一样。
Perl 5及更早版本将Perl源代码解析为内部列表或树,但我认为除了在理论上可能称之为编译器外,它不应该被称为一个真正的编译器。 它通常不输出与编译器相关联的任何字节码,汇编或实际机器代码。Perl的解析阶段用于检查Perl语法的有效性,以便在运行之前“编译”源文件。
它被调用方式如下:
perl -c myprog.pl
但是如果您查看Perl选项的帮助文档,实际上-c代表"检查"。
-c check syntax only (runs BEGIN and CHECK blocks)
(更复杂的是,Perl 5原本支持写出内部字节码,但在版本5.10中被移除了。大概是因为有bug吧,我也不知道。)
另一方面,如果你认为编译是将源代码解析成任何其他形式的表示形式的行为,那么这种解析使得Perl成为一种编译语言。在执行之前,Perl必须完全解析源文件。根据这个定义,在解析之前能立即开始执行源文件的任何语言都是一种解释性语言。
第三种看法是从领域专业人士最常使用的“解释”和“编译”这两个词的角度来考虑。我敢打赌,如果一个随机的程序员子集在思考Perl时被要求选择“编译”或“解释”,大多数人会选择“解释”。不是因为对Perl本质的理论争论,而是因为“编译”通常引起“编译”、“链接”、“目标代码”等方面的思考,而“解释”则被理解为“编写代码,试用它”。正确与否,这可能是在试图确定Perl是否真正是解释性或者实际上是编译性时需要知道的。在你的探索过程中,你会遇到很多争论。
(let ((a b)) c)
这样的内容,并将其转换成内存中的一棵树。但是,通过遍历树来运行该语句和生成代码之间有所区别。 - KazPerl5既是编译器又是解释器。Perl5将源代码编译成OPCODE对象,然后解释这些OPCODE对象。下面是详细说明。
维基百科的定义如下:
编译器是一种将用编程语言编写的源代码(源语言)转换为另一种计算机语言(目标语言,通常具有二进制形式,即目标代码)的计算机程序(或一组程序)。
Perl5是一种编译器。它接受Perl5源代码并生成OPCODE对象图。
$ perl -MO=Concise,-exec -E'for (1..3) { say "Hello, World!" }'
1 <0> enter
2 <;> nextstate(main 48 -e:1) v:%,2048
3 <0> pushmark s
4 <$> const(IV 1) s
5 <$> const(IV 3) s
6 <$> gv(*_) s
7 <{> enteriter(next->c last->f redo->8) lKS/8
d <0> iter s
e <|> and(other->8) vK/1
8 <;> nextstate(main 47 -e:1) v:%,2048
9 <0> pushmark s
a <$> const(PV "Hello, World!") s
b <@> say vK
c <0> unstack v
goto d
f <2> leaveloop vK/2
g <@> leave[1 ref] vKP/REFC
-e syntax OK
然而,Perl5编译器并不会生成机器码。那么OPCODE图是如何执行的呢?根据维基百科的一个定义,解释器是指“显式地执行由解释器系统中编译器生成的存储的预编译代码”,这意味着OPCODE图是被解释执行的。目前正在进行工作,以提供将Perl5编译为LLVM字节码的选项。然后,可以将其JIT编译为机器码。这与Java使用的方法相同。Raku(Perl 6)具有与Perl 5的兼容模式,因此可以使用Rakudo将Perl 5编译为JVM和Parrot。我希望能够使用LLVM进行编译!
这是一个可以在不需要C的情况下编译的虚拟机。然而,它的虚拟机比Java快得多,因此没有任何东西可以与之相比。
缺点 - 它像C++一样推崇成为全能瑞士军刀。在Perl的情况下,它去掉了训练轮、安全和边界。例如,在大多数面向对象编程语言中,您必须在使用对象之前声明一个类,在Perl中,对于您可以混合和匹配的类型没有限制,从而将任何东西转换为对象或将对象转换为任何东西。如果您已经了解面向对象编程,这个概念非常令人困惑,没有限制既是强大的也是Perl的缺点。因此,无论语言是否编译,问题都不在于您是否能够有效地推理出某些内容,而在于您是否会破坏整个世界。另一个问题是Perl是只写的,因此一旦编写,所有内容看起来都像乱码,并且变得难以分析甚至调试。
两者都有。首先,Perl 6脚本被编译成字节码(并进行了优化)。然后执行它(但是,您仍然需要Perl解释器)。 字节码是一种可执行代码,与其运行的环境无关(相同的字节码可以在ARM处理器上的Unix环境、x86架构的Windows系统和x64架构的Haiku上运行)。
Perl 6可以编译为Parrot VM(虚拟机)字节码。Python和Ruby也使用Parrot VM。
这就是使Perl、Ruby和Python比PHP更快的原因,因为PHP只是解释执行的(也可以编译,但需要第三方组件)。
perlcc
。perlcc
试图序列化Perl5的操作码。它从未是执行Perl5代码过程的一部分。 - ikegamiperlcc
时不要使用过去式。它只是从核心中分离出来,而不是被淘汰了。对它进行了大量的工作。 - tchrist