【问题标题】:What is the meaning of 'at compile-time' in Perl scripting?Perl脚本中的'at compile-time'是什么意思?
【发布时间】:2015-06-13 01:59:12
【问题描述】:

我读过这篇关于 Perl 的文章:

Perl 是一种解释型语言,不能编译。

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

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

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

Perl 真的可以编译脚本吗? Perl脚本中的'at compile-time'是什么意思?

【问题讨论】:

    标签: perl runtime compile-time


    【解决方案1】:

    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.
    

    【讨论】:

      【解决方案2】:

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

      来自perlrun

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

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

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

      再一次,这通常是可取的 - 在程序中途被故障绊倒通常更烦人,因为您可能处于不一致的状态。

      但是,正如您所注意到的 - 模块之类的东西可能非常大,因此“动态”加载它们可能很有用。 Perl 可以随时重新定义一堆东西——如果你真的想要,你可以在你的代码中创建/更改子例程。

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

      【讨论】:

      • 很多use strict;use warnings; 错误实际上是在运行时捕获的。 (例如$x="abc"; $x-&gt;{def}print undef;
      【解决方案3】:

      看看How a Perl 5 Program Works。 它指出

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

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

      【讨论】:

        猜你喜欢
        • 2013-10-21
        • 2018-03-05
        • 2017-02-27
        • 2019-03-18
        • 2010-12-28
        • 2017-04-28
        • 2023-01-11
        • 2018-08-30
        • 2023-03-25
        相关资源
        最近更新 更多