perl - 在 perl 中检测声明的包变量

标签 perl variables declaration

给定

# package main;
our $f;
sub f{}
sub g {}
1;

如何确定 $f ,但不是 $g ,已经宣布了吗?袖手旁观,我以为*{main::g}{SCALAR}可能未定义,但它是真正的 SCALAR 引用。

背景:我想将一个变量导入 main:: , 但如果该变量已声明,则为 carp 或 croak。

编辑 添加了 f响应@DVK 的初始回答的子程序。

回答 (2010-07-27)

这并不容易,但有可能。

一个 eval technique是最便携的,在 5.10 之前的 perls 上工作。在最近的 perls 中,像 Devel::Peek 这样的内省(introspection)模块和 B 可以歧视。

最佳答案

总结

在这一点上,经过相当广泛的研究,我坚定地认为,在一个名为“X”的符号表条目被声明但未分配给它的情况下,它是。无法普遍区分 glob 中的哪些引用类型实际上是通过对 Devel::的深入探测而声明的。

换句话说,您只能说出以下两种不同的情况:

  • X 根本没有声明(符号表条目不存在)
  • X 已声明,并且某些 glob 类型实际上已分配给。

    在第二种情况下,
  • 可以查找分配给哪些 glob 类型,哪些不是
  • 但是,你不能找出哪些未分配给 glob 类型是声明和未分配的,哪些是根本没有声明的。

  • 换句话说,对于 our $f = 1; our @f; ;我们可以看出$main::f是一个标量;
    但我们无法判断 @f%f是否已声明 - 它与 our $f = 1; our %f; 完全没有区别.

    请注意,子例程定义也遵循第二条规则,但是声明一个命名的 sub 会自动为其分配一个值(代码块),因此您永远不能有一个处于“已声明但未分配给”状态的子名称(警告:原型(prototype)可能不是真的???没有线索)。
    原始答案

    好吧,将标量与子例程区分开来的非常有限(恕我直言有些脆弱)的解决方案可能是使用 UNIVERSAL::can:
    use strict; 
    our $f; 
    sub g {};
    foreach my $n ("f","g","h") {
        # First off, check if we are in main:: namespace, 
        # and if we are, that we are a scalar
        no strict "refs"; 
        next unless exists $main::{$n} && *{"main::$n"}; 
        use strict "refs"; 
        # Now, we are a declared scalr, unless we are a executable subroutine:
        print "Declared: \$$n\n" unless UNIVERSAL::can("main",$n)
    }
    

    结果:
    Declared: $f
    

    请注意 {SCALAR}在我的测试中似乎无法清除非标量 - 它很高兴地通过了 @A%H如果我声明它们并添加到循环中。

    更新

    我从“掌握 perl”的第 8 章尝试了 brian d foy 的方法,但不知何故无法让它适用于标量、散列或数组;但正如 draegtun 所述,它适用于子程序或变量 已分配给 :
    > perl5.8 -we '{use strict; use Data::Dumper; 
      our $f; sub g {}; our @A=(); sub B{}; our $B; our %H=();
      foreach my $n ("f","g","h","STDOUT","A","H","B") {
          no strict "refs"; 
          next unless exists $main::{$n};
          print "Exists: $n\n";
          if ( defined ${$n}) { print "Defined scalar: $n\n"}; 
          if ( defined @{$n}) { print "Defined ARRAY: $n\n"}; 
          if ( defined %{$n}) { print "Defined HASH: $n\n"}; 
          if ( defined &{$n}) { print "Defined SUB: $n\n"}; 
          use strict "refs";}}'       
    
    Exists: f
    Exists: g
    Defined SUB: g           <===== No other defined prints worked
    Exists: STDOUT
    Exists: A
    Exists: H
    Exists: B
    Defined SUB: B           <===== No other defined prints worked
    

    关于perl - 在 perl 中检测声明的包变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3335425/

    相关文章:

    php - 如何在 CSS 样式中使用 PHP 变量?

    python - 递归中的全局变量。 Python

    java - 不同方法中的变量放在一起

    c++ - 在循环外声明 var 不好吗?

    perl - 我应该将超长的 UTF-8 字符串转换为最短的正常形式吗?

    perl - 按名称获取 Unicode 代码点 ("character")

    Perl 连接

    perl - 在 Perl 中模拟父类(super class)调用(使用 Test::MockObject)

    c - 为什么这段代码中的 `bar`没有静态存储持续时间?

    css - 声明中的选择器?