在编译时'是什么意思?在Perl脚本中

时间:2015-04-08 08:01:25

标签: perl runtime compile-time

我读过有关perl的信息:

  

Perl是一种解释型语言,无法编译。

我还看到了关于at compile-timeat run-time的讨论。

特别是当我寻找userequire的使用时,它会显示出不同之处:

  

use通常在编译时加载模块 ,而require在运行时

所以我的问题是Perl真的编译脚本吗? perl脚本编写中“编译时”的含义是什么?

3 个答案:

答案 0 :(得分:5)

Perl代码在执行之前编译,而不是机器代码。这有点像Java编译为字节代码,但结果是更高级别。

# B::Concise shows the opcode tree that results from compiling Perl code

$ perl -MO=Concise,-exec -e'print("Hello, world!\n") for 1..3;'
1  <0> enter
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark s
4  <$> const[IV 1] s
5  <$> const[IV 3] s
6  <#> gv[*_] s
7  <{> enteriter(next->b last->e redo->8) lKS/8
c  <0> iter s
d  <|> and(other->8) vK/1
8      <0> pushmark s
9      <$> const[PV "Hello, world!\n"] s
a      <@> print vK
b      <0> unstack v
           goto c
e  <2> leaveloop vK/2
f  <@> leave[1 ref] vKP/REFC
-e syntax OK

当要求Perl执行文件时(因为它已传递给perlrequiredo EXPReval EXPR),它首先编译整个文件,然后执行它刚编译的代码。

如果在编译阶段遇到任何useBEGIN,则在完成编译后会立即执行use语句或BEGIN块。

# -c causes the main program to be compiled but not executed.

$ perl -c -E'
   say "abc";
   BEGIN { say "def"; }
   say "ghi";
'
def
-e syntax OK

$ perl -E'
   say "abc";
   BEGIN { say "def"; }
   say "ghi";
'
def
abc
ghi

可以在编译时检测到某些错误。

$ perl -c -E'say "abc" "def";'
String found where operator expected at -e line 1, near ""abc" "def""
        (Missing operator before  "def"?)
syntax error at -e line 1, near ""abc" "def""
-e had compilation errors.

其他人不能。

$ perl -c -E'$x={}; $x->[0]'
-e syntax OK

$ perl -E'$x={}; $x->[0]'
Not an ARRAY reference at -e line 1.

答案 1 :(得分:4)

Perl在运行之前编译。通常这是在之前完成的。运行perl -c将执行相当基本的代码有效性检查,并将突出显示某些类型的错误(通常在我的情况下,缺少分号)。

来自perlrun

  

找到程序后,Perl会将整个程序编译为内部表单。如果存在任何编译错误,则不会尝试执行程序。 (这与典型的shell脚本不同,后者可能会在找到语法错​​误之前部分运行。)

包括加载和检查任何导入的模块以进行相同的测试。在大多数情况下,这正是您想要的 - 这些测试/错误通常显示停止者,因此在开始执行之前进行检测是一件好事。

特别是当您use strict;use warnings;时,您的代码会针对更广泛的错误进行预处理。它在编译时完成,如果发现任何内容,它将中止。

同样,这通常是理想的 - 在程序中途绊倒故障通常更难以理清,因为你可能处于不一致的状态。

然而,正如您所注意到的那样 - 模块之类的东西可能非常大,因此可以在运行时加载它们。 Perl可以在你去的时候重新定义一堆东西 - 如果你真的想要你可以在你的代码中制作/更改子程序。

由于所谓的暂停状态问题,在“编译时”不能对子例程进行更改并测试其有效性。因此,您在运行时加载,但然后必须构建一些更详尽的完整性检查。

答案 2 :(得分:2)

看看How a Perl 5 Program Works。 它说明了

  

Perl 5程序有两个不同的执行阶段:编译时和运行时。

它还描述了compile timeruntime之间的区别。