$ref = \%hash;
$ref = \@hash;
如何在 perl中使用typeglob做与引用相同的事情?
perl 解释的确切步骤是$$ref{key}
什么?
使用perlref 文档的*foo{THING}
Make References 部分中记录的语法。
可以使用一种特殊的语法来创建引用,这种语法被人们亲切地称为
*foo{THING}
语法。*foo{THING}
返回对 THING 槽的引用*foo
(这是符号表条目,其中包含所有称为 的内容foo
)。$scalarref = *foo{SCALAR}; $arrayref = *ARGV{ARRAY}; $hashref = *ENV{HASH}; $coderef = *handler{CODE}; $ioref = *STDIN{IO}; $globref = *foo{GLOB}; $formatref = *foo{FORMAT};
例如:
#! /usr/bin/env perl
use strict;
use warnings;
our %hash = (Ralph => "Kramden", Ed => "Norton");
our @hash = qw/ apple orange banana cherry kiwi /;
my $ref;
$ref = *hash{HASH};
print $ref->{Ed}, "\n";
$ref = *hash{ARRAY};
print $ref->[1], "\n";
输出:
诺顿 橙
至于你问题的第二部分,添加
print $$ref{Ralph}, "\n";
在 Ed 产生预期的输出之后。编译器为此行生成代码,该代码经过以下顺序:
$ref
.$ref
的东西。但不要相信我的话。为了减少输出量,考虑一个类似的两线:
my $ref = { Ralph => "Kramden" };
print $$ref{Ralph};
使用为调试编译的 perl 运行它让我们
$ debugperl -Dtls 参考 [...] (参考:1)下一个状态 => (参考:2)pushmark => * (ref:2) padsv($ref) # 第 1 步 => * \HV() (ref:2) rv2hv # 第 2 步 => * 高压() (ref:2) const(PV("Ralph"\0)) # STEP 3a => * HV() PV("拉尔夫"\0) (ref:2) helem # STEP 3b => * PV("克拉姆登"\0) (参考:2)打印 => SV_YES (ref:2) 离开 [...]
请注意,对于全局变量,它略有不同。
我不确定您的更大意图是什么,但有一些重要的警告。请注意,typeglob 表示符号表条目,因此您无法以这种方式获取词法,因为它们存在于 pad 中,而不是符号表中。例如,假设您在上面代码中my @hash = ("splat");
的赋值之前插入$ref
。结果可能会让你大吃一惊。
$ ./编 “我的”变量 @hash 掩盖了 ./prog 第 11 行相同范围内的早期声明。 诺顿 橙
关于标量的行为也可能令人惊讶。
*foo{THING}
undef
如果该特定 THING 尚未使用,则返回,标量除外。如果尚未使用,*foo{SCALAR}
则返回对匿名标量的引用。$foo
这可能会在未来的版本中改变。
告诉我们您想要做什么,我们将能够为您提供具体、有用的建议。
如果您要问如何获得对类型 glob 的引用,那就是:
my $ref = \*symbol_name_here;
对于符号的“字面名称”(即您输入符号的确切名称的位置),而不是变量。但是,您可以这样做:
my $ref = Symbol::qualify_to_ref( $symbol_name );
对于变量符号。但是,以上适用,strict
而以下更简单的则不适用:
my $ref = \*{$symbol_name};
的好处之一Symbol::qualify*
是它将包名称作为第二个变量处理。所以...
my $sref = Symbol::qualify_to_ref( $symbol_name, $some_other_package );
做同样的事情\*{$some_other_package.'::'.$symbol_name}
,它适用于strict
.
一旦你有了符号 ref,为了得到这个槽,你必须尊重这个引用,所以 perl 不认为你正在尝试将它用作哈希,就像这样。
my $href = *{ $sref }{HASH};
my $code = *{ $sref }{CODE};
my $arref = *{ $sref }{ARRAY};
my $io = *{ $sref }{IO};
我以不同的方式把你的两个想法放在一起。如果你有一个符号表引用,你可以得到这个HASH
槽,这是一个引用,就像对哈希的任何其他引用一样。因此,您可以执行以下操作。
任何一个
*hash{HASH}->{key}
或者
${ *hash{HASH} }{key}
将工作。不过这些更安全
( *hash{HASH} || {} )->{key};
${ *hash{HASH} || {} }{key};
如果您不想使用直接条目,而是使用对表的引用来执行此操作,您可以执行以下操作:
my $ref = \*hash;
my $value = *{ $ref }{HASH} && *{ $ref }{HASH}->{key};
注意: %hash
绝对需要是一个包变量。只有包变量驻留在符号表中(因此只有 subs@ISA
和 Exporter 变量往往在现代符号表中)。词法变量(那些声明my
的)驻留在“pad”中。
更新:
我已经摆脱了使用Symbol
这么多。奇怪的是,即使它是core,它在 Perlers 所做的和看到的事情上似乎是非标准的。相反,我在我所谓的“无块”中使用直接方式,尽可能本地化。
# All I want is one symbol.
# Turn strict-refs off, get it, turn it back on.
my $symb = do { no strict 'refs'; \*{$symbol_name} };
或者
{ no strict 'refs';
*{$package_name.'::'.$symbol_name} = $sub_I_created;
... # more reckless symbol table mucking...
}
我几乎总是使用*STDERR{IO}
成语作为 glob 文件句柄引用。在现代 Perl 中,这些通常是对象。
my $fh = *STDERR{IO};
say blessed( $fh ); # IO::File
$fh->say( 'Some stuff' );
我不认为你可以用 typeglobs 做与引用一样的事情(例如,词法变量从不涉及类型 glob)。你最终想要达到什么目的?
至于$$ref{key}
, perl 进行如下:
{...}
必须$ref
是哈希引用Perl 以实验性着称:
尝试:
perl -MO=Terse -e' $ref = \%hash; $ret = $$ref{key}'
或者:
perl -MO=Debug -e' $ref = \%hash; $ret = $$ref{key}'
一切都会被揭示。如果你有一个调试 Perl,你甚至可以这样做:
perl -Dt -e'$ref = \%hash; $ret = $$ref{key}'