$ref = \%hash;
$ref = \@hash;
如何在perl中使用 typeglob 执行相同的操作?
perl解释$$ref{key}
的确切步骤是什么?
答案 0 :(得分:9)
使用*foo{THING}
语法,该语法记录在perlref文档的Making References section中。
可以使用特殊语法(称为
*foo{THING}
语法)创建引用。*foo{THING}
返回对*foo
中THING位置的引用(这是包含所有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";
输出:
Norton orange
关于问题的第二部分,请添加
print $$ref{Ralph}, "\n";
在Ed产生预期输出后。编译器为此行生成代码,该代码按以下顺序生成:
$ref
。$ref
的东西。但是不要相信我的话。要减少产量,请考虑类似的两线:
my $ref = { Ralph => "Kramden" };
print $$ref{Ralph};
使用为调试编译的perl运行它会让我们
$ debugperl -Dtls ref [...] (ref:1) nextstate => (ref:2) pushmark => * (ref:2) padsv($ref) # STEP 1 => * \HV() (ref:2) rv2hv # STEP 2 => * HV() (ref:2) const(PV("Ralph"\0)) # STEP 3a => * HV() PV("Ralph"\0) (ref:2) helem # STEP 3b => * PV("Kramden"\0) (ref:2) print => SV_YES (ref:2) leave [...]
请注意,它与全局变量略有不同。
我不确定你的意图是什么,但有一些重要的警告。请注意,typeglob表示符号表条目,因此您不能以这种方式获取词汇,因为它们存在于pad中,而不是符号表中。例如,假设您在上面代码中my @hash = ("splat");
的分配之前插入$ref
。结果可能让你大吃一惊。
$ ./prog "my" variable @hash masks earlier declaration in same scope at ./prog line 11. Norton orange
关于标量的行为也可能令人惊讶。
*foo{THING}
如果尚未使用特定的THING,则会返回undef
,但标量除外。如果尚未使用*foo{SCALAR}
,则$foo
会返回对匿名标量的引用。这可能会在将来的版本中发生变化。
告诉我们您要做的事情,我们将能够为您提供具体,有用的建议。
答案 1 :(得分:6)
如果你问如何获得类型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} };
OR
{ 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' );
答案 2 :(得分:1)
我认为你不能像使用引用一样对typeglobs做同样的事情(例如词法变量从不涉及类型glob)。你到底想要达到什么目的?
至于$$ref{key}
,perl按如下方式进行:
{...}
表示$ref
必须是哈希引用答案 3 :(得分:0)
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}'