gpt4 book ai didi

perl - 为什么子程序需要在其中使用的变量声明之后编写?

转载 作者:行者123 更新时间:2023-12-03 16:53:49 26 4
gpt4 key购买 nike

让我们假设我们有这段代码,为什么它会因显式包名称错误而失败,因为该函数仅在 $value 声明之后才被调用。 ?

use strict;
use warnings;

sub print_value{
print "\n$value";
}

my $value = 2;
print_value();

这在编译时失败:
Global symbol "$value" requires explicit package name at file.pl line 5.
Execution of file.pl aborted due to compilation errors.

这段代码工作得很好:
use strict;
use warnings;

my $value = 2;
print_value();

sub print_value{
print "\n$value";
}

忽略这种编程风格的无用性或已弃用的编码风格,只关注上下文。

最佳答案

这是因为scope .这就是您的程序中您的变量可见的地方。您的 $value是一个词法变量,因为你已经用 my 声明了它.这意味着,它存在于某个范围内(以及该范围内的所有范围)。在您的两个示例中,范围是整个文件(也可以称为全局范围)。

Perl 分两个阶段查看您的代码。第一个是编译时,它检查语法并加载依赖项(如 use 语句)。此时,它将查找$value 的可用性。函数内部。

Perl 会在这些地方查看:

  • 当前作用域内的词法( myour )变量。

    如果引用它的代码跟在声明之后,并且它与声明在同一个块中,或者块嵌套在该块中,则该变量在范围内(即变量是可见的)。文件本身是一个块, curl 形成其他块。

    如果作用域中有多个同名的词法变量,则最近声明的变量会掩盖其他变量。这意味着在函数本身中声明的变量将在函数外部的变量之前使用。
    my $i;          # +--------- $i is in scope (visible) here
    my $x; # | +------- $x is in scope (visible) here
    while (...) { # | |
    my $j; # | | +---- $j is in scope (visible) here
    my $x; # | | +-- This different $x is in scope (visible) here
    ... # | v v
    } # | |
    sub foo { # | |
    my $j; # | | +---- This different $j is in scope (visible) here
    my $x; # | | +-- This third $x is in scope (visible) here
    ... # | v v
    } # | |
    ... # v v
  • 包变量

    这些是全局变量(未声明,或使用 use vars 声明)。

    Perl 将查看范围内最新“包”声明的命名空间(默认为 main ),“ super 全局”变量除外。这是指 Perl 在 $_ 中查找的符号变量(如 $$main 等)。而不是当前的包。

  • $value还没有被声明,Perl 认为它意味着包变量 $main::value (因为 main 是默认包)。
    use strict;            # | Code here will use package var $main::value
    use warnings; # |
    # |
    sub print_value{ # |
    print "\n$value"; # |
    } # |
    # v
    my $value = 2; # | Code here will use this lexical var $value
    print_value(); # v

    这一切都不是因为你有 strict打开。只有你必须声明变量的事实,要么使用 my , 或 our或者使用完全限定名称是因为 use strict .

    如果您没有 strict并且没有用 my 声明变量,你的程序会工作。 $value在这种情况下将是一个包变量。

    在您的第二个示例中,您声明了 $value在子程序之前,所以 Perl 在编译时知道会有一个 $value在那个范围内可用,所以它不会提示。
    use strict;            # | Code here will use package var $main::value
    use warnings; # |
    # v
    my $value = 2; # | Code here will use this lexical var $value
    print_value(); # |
    # |
    sub print_value{ # |
    print "\n$value"; # |
    } # v

    但是,更好的方法是将变量作为参数传递给 print_value .
    use strict;
    use warnings;

    sub print_value{
    my $arg = shift;
    print "\n$arg";
    }

    my $value = 2;
    print_value($value);

    现在 Perl 看到有一个 $arg小范围内。它不知道它的值(value),但它不必知道。和 $value在使用它之前也已经声明了。

    切勿在函数内部使用全局范围(整个文件)中的变量。始终将它们作为参数传递 1。

    以下是一些相关链接:
  • Tutorial on scope on perlmaven
  • order of execution in perlmod

  • 1) 除非你想构建一个单例或其他类型的 closure

    关于perl - 为什么子程序需要在其中使用的变量声明之后编写?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39896940/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com