[英]How do I do the same thing as reference using typeglob in perl?
$ref = \%hash;
$ref = \@hash;
如何在 perl 中使用typeglob執行與引用相同的操作?
perl 解釋$$ref{key}
的確切步驟是什么?
使用*foo{THING}
語法,該語法記錄在 perlref 文檔的制作參考部分。
可以使用一種特殊的語法來創建引用,這種語法被稱為
*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";
Output:
Norton orange
至於你問題的第二部分,添加
print $$ref{Ralph}, "\n";
在 Ed 產生預期的 output 之后。 編譯器為此行生成代碼,該代碼經過以下順序:
$ref
的 pad 條目。$ref
的東西。但不要相信我的話。 要減小 output 的體積,考慮類似的兩線:
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
尚未使用,*foo{SCALAR}
返回對匿名標量的引用。 這可能會在未來的版本中改變。
告訴我們您想要做什么,我們將能夠為您提供具體、有用的建議。
如果您要問如何獲得對類型 glob 的引用,那就是:
my $ref = \*symbol_name_here;
對於符號的“字面名稱”(即您輸入符號的確切名稱的位置),而不是變量。 但是,您可以這樣做:
my $ref = Symbol::qualify_to_ref( $symbol_name );
對於變量符號。 但是,以上適用於strict
,而以下較簡單的則不適用:
my $ref = \*{$symbol_name};
Symbol::qualify*
的優點之一是它將 package 名稱作為第二個變量處理。 所以...
my $sref = Symbol::qualify_to_ref( $symbol_name, $some_other_package );
與\*{$some_other_package.'::'.$symbol_name}
做同樣的事情,它適用於strict
。
一旦有了符號 ref,要獲得插槽,就必須尊重參考,因此 perl 不認為您正在嘗試將其用作 hash,就像這樣。
my $href = *{ $sref }{HASH};
my $code = *{ $sref }{CODE};
my $arref = *{ $sref }{ARRAY};
my $io = *{ $sref }{IO};
我以不同的方式把你的兩個想法放在一起。 如果您有符號表引用,您可以獲得HASH
插槽,它就像對 hash 的任何其他引用一樣。 因此,您可以執行以下操作。
任何一個
*hash{HASH}->{key}
或者
${ *hash{HASH} }{key}
將工作。 不過這些更安全
( *hash{HASH} || {} )->{key};
${ *hash{HASH} || {} }{key};
如果您不想使用直接條目,而是使用對表的引用來執行此操作,您可以執行以下操作:
my $ref = \*hash;
my $value = *{ $ref }{HASH} && *{ $ref }{HASH}->{key};
注意: %hash
絕對需要是 package 變量。 只有 package 變量駐留在符號表中(因此只有 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
必須是 hash 引用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}'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.