在Perl中检测已声明的包变量 [英] Detecting declared package variables in perl

查看:45
本文介绍了在Perl中检测已声明的包变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出

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

如何确定 $ f ,但没有声明 $ g ?袖手旁观,我以为 * {main :: g} {SCALAR} 可能是不确定的,但这是善意 SCALAR ref。

How can I determine that $f, but not $g, has been declared? Off the cuff, I'd thought that *{main::g}{SCALAR} might be undefined, but it is a bona fide SCALAR ref.

背景:我想将变量导入 main :: ,但是如果是鲤鱼或鱼,该变量已经声明。

Background: I'd like to import a variable into main::, but carp or croak if that variable is already declared.

EDIT 添加了 f 子例程来响应@ DVK的最初答案。

EDIT Added an f subroutine in response to @DVK's initial answer.

ANSWER(2010-07-27)

此并非易事,但有可能。

This isn't easy, but it is possible.

一个 eval 技术是最可移植的,适用于5.10之前的perl。在最近的Perls中,内省模块如 Devel: :Peek B 可以区分。

An eval technique is most portable, working on perls older than 5.10. In more recent perls, introspective modules like Devel::Peek and B can discriminate.

推荐答案

我尽力了,甚至试图询问 eval STRING 是否已经通过<$ c $声明了 $ main :: f c>我们的或我的。 (这需要复制,关闭和稍后恢复 STDERR 来减少聊天情况。)更改了程序包后,这些声明在临时切回中不再可见。

I gave it my best, even going so far as trying to ask eval STRING whether $main::f had been declared via our or my. (This required duping, closing, and later restoring STDERR to cut down on the chattiness.) Once you've changed packages, those declarations no longer seem visible on a temporary switchback.

下面的技术将检测是否已通过


$ b声明了 $ f $ b

The technique below will detect whether $f has been declared via

use vars qw/ $f /;

以下代码:

package MyModule;

use warnings;
use strict;

# using $f will confuse the compiler, generating
# warnings of 'Variable "%f" is not available'
# although we're going for $main::f
my $__f = "from MyModule";

my %IMPORT_OK = (
  '$f' => [f => \$__f],
);

sub import {
  my($pkg,@imports) = @_;
  my $callpkg = caller;

  die "I don't speak your dirty Pig-Latin"
    if $callpkg !~ /\A\w+(::\w+)*\z/ ||
       grep !/\A[\$@%]\w+\z/, @imports;

  foreach my $name (@imports) {
    my($sym,$ref) = @{ $IMPORT_OK{$name} || [] };
    die "unknown import: $name" unless $sym;

    open my $saverr, ">&", \*STDERR or die "dup STDERR: $!";
    close STDERR;

    my $declared = eval qq{
      package $callpkg;
      my(undef)=$name;
      1;
    };

    open STDERR, ">&", $saverr or print "restore STDERR: $!";
    die "${callpkg}::$sym already exists" if $declared;

    {
      no strict 'refs';
      *{$callpkg . "::" . $sym} = $ref;
    }
  }
}

1;

这篇关于在Perl中检测已声明的包变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆