2011-11-16 71 views
10

在上一個answer to a question about hash slices評論,有人想知道如何使用箭頭語法通過散列引用來訪問一個哈希片,心想也許是

@$ref->{@keys} 

會這樣做。

是的,正確的語法是@$ref{@keys}@{$ref}{@keys},但這不在這個問題的重點。

我試圖算出與一個箭頭的表達需要的數據結構:

#! /usr/bin/env perl 

use strict; 
use warnings; 

my $ref = {"a" => 1, "b" => 2, "c" => 3}; 

my @keys = qw/ a b c /; 

#$ref = [ { a => 9, b => 8, c => 7 } ]; 
#$ref = [ { a => {}, b => {}, c => {} } ]; 
print @$ref->{@keys}, "\n"; 

作爲寫入時,代碼失敗

Not an ARRAY reference at ./prog line 12.

有道理:@$ref想要的參考一個數組,所以我嘗試在一個匿名數組的引用內包裝哈希引用。這些嘗試失敗,

Can't use an undefined value as a HASH reference at ./prog line 12.

跟蹤輸出是

$ debugperl -Dt prog 
[...] 
(prog:12) pushmark 
(prog:12) padsv($ref) 
(prog:12) rv2av 
(prog:12) rv2hv 
Can't use an undefined value as a HASH reference at prog line 12.

print行的語法轉儲

$ debugperl -Dx prog 
[...] 
    { 
484  TYPE = print ===> 2 
     FLAGS = (VOID,KIDS) 
     { 
485   TYPE = pushmark ===> 486 
      FLAGS = (SCALAR) 
     } 
     { 
372   TYPE = helem ===> 371 
      FLAGS = (SCALAR,KIDS) 
      { 
487    TYPE = rv2hv ===> 361 
       TARG = 5 
       FLAGS = (SCALAR,KIDS,REF) 
       PRIVATE = (STRICT_REFS) 
       { 
373     TYPE = rv2av ===> 487 
        TARG = 4 
        FLAGS = (SCALAR,KIDS,REF) 
        PRIVATE = (STRICT_REFS) 
        { 
486      TYPE = padsv ===> 373 
         TARG = 1 
         FLAGS = (SCALAR,MOD) 
        } 
       } 
      } 
      { 
361    TYPE = padav ===> 372 
       TARG = 2 
       FLAGS = (SCALAR) 
      } 
     } 
     { 
371   TYPE = const ===> 484 
      TARG = 19 
      FLAGS = (SCALAR) 
     } 
    } 
[...]

哪裏是未定義的值是從哪裏來的?程序的$ref的值是否正常終止?

回答

8

這是無效的(或至少沒有意義)Perl語法—我有點驚訝它沒有被標記爲語法錯誤。

我首先想到的是它試圖評估標量上下文中的數組@$foo,並將結果用作哈希引用,但這看起來不太像是發生了什麼。相反,從發佈的調試輸出看,它更像是試圖直接使用內部數組變量(AV)結構作爲散列引用(RV),這是一種標量類型(SV;請參閱perlguts瞭解詳細信息)。

我還沒有看過源代碼,但它看起來好像rv2hv例程要麼注意到它被給出了錯誤的結構類型並返回null,或者只是試圖使用AV作爲RV並實現相同這種方式的效果。 (對不起,如果聽起來有點混亂,我上次查看perl的內部已經有幾年了。)

你可能要考慮提交一個bug報告。

順便說一句,一個簡單的測試案例,演示效果只是@foo->{bar}

+0

它是有效的(即使沒有意義),因此它不應該是語法錯誤。不過,這應該是一個嚴格的錯誤。 – ikegami

5
@$ref->{@keys} 

意味着

scalar(@$ref)->{@keys} 

所以它應該是相當於

my $ref2 = @$ref; 
$ref2->{@keys} 

它不是,所以這是一個錯誤。它仍然存在於將成爲Perl 5.16.0的近期狀態中。 (v5.15。4,具體)

請使用perlbug命令行工具報告。 (只需輸入perlbug並回答幾個簡單的問題。)