簡體   English   中英

如何在 perl 中使用 typeglob 執行與引用相同的操作?

[英]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 之后。 編譯器為此行生成代碼,該代碼經過以下順序:

  1. 獲取$ref的 pad 條目。
  2. 獲取$ref的東西。
  3. 從步驟 2 中查找 hash 中的密鑰。

但不要相信我的話。 要減小 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 進行如下:

  • 第一個 $ 告訴它返回一個標量
  • 在 sigil 之后存在變量表明該變量必須是引用
  • {...}表示$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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM