27

Perl 是编译的还是解释的?

4

9 回答 9

57

你不会得到一个明确的答案,因为你没有提供一个明确的问题。

Perl 总是处于以下两种状态之一:要么正在编译,要么正在执行。这就是为什么你会看到“在编译时”与“在运行时”的讨论。通常,您会得到一个编译短语,然后是一个执行阶段,但不必如此。

这两个阶段也可以来回交易。Aneval STRING是解释器调用编译器的一种方式(因此也是do FILEand require)。块是编译器调用解释器的一种BEGIN方式(因此也是useand no)。

当你运行时perl -c,你省略了运行时阶段。有多种方法可以跳过编译时阶段,但没有一种是特别方便或常见的。Apachemod_perl只编译一次脚本,但会执行多次。如果您使用 Byteloader,您也可以这样做。等等。

Perl 是编译还是解释的正确答案是肯定的。

于 2011-03-21T12:12:25.873 回答
27

好吧,这取决于您所说的编译语言是什么意思。也许这就是谷歌搜索没有为您的问题带来明确答案的原因。

一种观点认为,编译意味着从一个源代码描述编译到另一个,即代码生成

如果我们接受这些前提,那么 Perl 6 可以编译,而 Perl 5 和更早的版本是解释型语言。

Perl 6 专门编译为Parrot 字节码。因此 Perl 6 是一种正确编译的语言,就像Java 是.

Perl 5 和更早版本将 Perl 源代码解析为内部列表或树,但我认为它不应该被称为适当的编译器,除非在理论上。它不输出任何通常与编译器相关的字节码、汇编或真实机器码。Perl 用于检查 Perl 语法的解析阶段曾经被称为“编译”源代码。它用于在不运行 Perl 源文件的情况下检查其语法有效性。

它被调用为:

perl -c myprog.pl

但是,如果您查看 Perl 选项的帮助,-c 实际上代表“检查”。

-c                check syntax only (runs BEGIN and CHECK blocks)

(更复杂的是,Perl 5 支持写出内部字节码,但它在 5.10 版本中被删除。大概是因为它有问题,我不知道。)

另一方面,如果您认为编译是将源代码树解析为任何其他类型的表示的行为,那么,这种解析使 Perl 成为一种编译语言。Perl 必须完全解析源文件才能开始执行它。根据这个定义,任何可以在解析之前立即开始执行源文件的语言都是解释语言。

第三种看待这一点的方法是从这些词“解释”和“编译”是该领域专业人士最常使用的。我敢打赌,如果在考虑 Perl 时要求程序员的随机子集选择“编译”或“解释”,大多数人会选择“解释”。不是因为关于 Perl 本质的一些理论争论,而是因为“已编译”通常会引发“编译”、“链接”、“目标代码”等思想,而“解释”则意味着“编写代码,尝试一下” ”。对或错,在试图确定 Perl 是真的解释还是编译时,这可能是件好事。你会在你的追求中遇到很多争论。

于 2011-03-21T10:48:54.953 回答
13

两个都。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 使用的方法相同。

于 2011-03-21T18:17:28.853 回答
1

Raku (Perl 6) 与 Perl 5 具有兼容模式,因此可以使用 Rakudo 将 Perl 5 编译为 JVM 和 Parrot。我想要 LLVM 来做这个!

于 2020-06-10T09:11:31.220 回答
0

Perl 是一种解释型语言。但是,它确实在内部编译成 p 代码以提高效率。

于 2011-03-21T10:50:56.593 回答
0

来自维基百科:“Perl 是一种高级、通用、解释型、动态编程语言”。Perl 6 还允许编译(再次参见Wikipedia)。

于 2011-03-21T10:54:18.783 回答
-1

两个都。首先,Perl 6 脚本被编译成字节码(并优化)。然后它被执行(但是,你仍然需要 Perl 解释器)。字节码是一种可执行代码,它独立于它运行的环境(相同的字节码可以在 ARM 处理器的 Unix 环境、x86 的 Windows 系统和 x64 的 Haiku 环境中运行)。

Perl 6 可以编译成 Parrot VM(虚拟机)字节码。Python 和 Ruby 也使用 Parrot VM。

这就是使 Perl、Ruby 和 Python 比 PHP 更快的原因,PHP 只是解释(也可以编译,但你需要 3rd 方组件)。

于 2011-03-21T10:55:27.183 回答
-1

它是一个虚拟机,也可以在不需要 C 的情况下进行编译。但是它的虚拟机比 Java 快几光年,所以真的没有任何东西可以与之相比。

坏处 - 就像 C++ 推动成为一把万能的瑞士军刀一样可怕。在 Perls 案例中,它移除了训练轮、安全性和边界。例如,在大多数 OOP 语言中,您必须先声明一个类,然后才能使用对象,而在 Perl 中,您可以混合和匹配任何东西,从而将任何东西变成对象或将对象变成任何东西,对类型没有任何限制。如果您已经了解 OOP,那么这个概念会非常混乱,缺乏限制既是强大的,也是 Perl 的一个缺点。因此,语言是否被编译并不是问题,因为你可以在不影响世界的情况下有效地推理某些事情。另一个问题是 Perl 是只写的,所以一旦写完,一切看起来都像胡言乱语,变得难以剖析甚至调试。

于 2020-01-11T09:00:43.870 回答
-2

最常被解释,但也可能被编译。 关于 perl 编译器

于 2011-03-21T10:50:59.693 回答