perl脚本编写中'at compile-time'的含义是什么?

5 perl runtime compile-time

我读过有关perl的内容:

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

我也看到了谈论at compile-timeat run-time.

特别是当我寻找使用use和时require,它显示了一个区别:

use通常加载模块在编译的时候,而require不会在运行时.

所以我的问题是Perl真的编译脚本吗?
perl脚本编写中"编译时"的意思是什么?

ike*_*ami 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
Run Code Online (Sandbox Code Playgroud)

当Perl是要求执行文件(因为它传递给perl,require,do 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
Run Code Online (Sandbox Code Playgroud)

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

$ 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.
Run Code Online (Sandbox Code Playgroud)

别人不能.

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

$ perl -E'$x={}; $x->[0]'
Not an ARRAY reference at -e line 1.
Run Code Online (Sandbox Code Playgroud)


Sob*_*que 4

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

perlrun

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

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

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

同样,这通常是可取的 - 在程序中途遇到故障通常更烦人,因为您可能处于不一致的状态。

然而,正如您所注意到的 - 像模块这样的东西可能非常大,因此“动态”加载它们可能会很有用。Perl 可以随时重新定义很多东西 - 如果您确实想要,可以在代码中创建/更改子例程。

由于所谓的暂停状态问题,对子例程的更改和测试其有效性永远无法在“编译时”完成。因此,您可以在运行时加载,但随后必须构建一些更详尽的完整性检查。

  • 许多“use strict;”和“use warnings;”错误实际上是在运行时捕获的。(例如 `$x="abc"; $x-&gt;{def}` 和 `print undef;`) (3认同)