2010-12-16 64 views
2

這是爲什麼這樣工作?這是2號線perl list散列引用的上下文

DB<1> $a = {'a'=>1}; $b = {'a'=>2, 'b'=>0}; 
DB<2> $c = ($a, $b); 
DB<3> print $c; 
    HASH(0x8743e68) 
DB<4> print $c->{a},$c->{b}; 
    20 

我明白,如果我小心使用%$和%$ B是Perl會知道我的意思,但在這裏僅列出裸裁判,爲什麼它的工作原理?

或者它看起來像它的工作,我真的做了別的?

+0

哦,要小心「太簡單」的測試。如果我使用了$ a = {'a'=> 1,'c'=> 3);我會看到失敗。 – Don 2010-12-16 22:39:58

+0

看起來像一個精心構造的問題。 – aartist 2010-12-16 22:56:19

回答

13

有一個在

$c = ($a, $b); 

而是沒有列表環境中,你看到的是在行動comma operator

二進制 「」 是逗號運算符。在標量上下文中,它評估其左側參數,將該值拋出,然後評估其正確參數並返回該值。這就像C的逗號操作符一樣。

爲了更清楚地看到這一點,看看:

#!/usr/bin/perl 
use strict; use warnings; 

my $x = {a => 1}; 
my $y = {a => 2, b => 0}; 

my $z = ($x, $y); 

print "\$x = $x\t\$y = $y\t\$z = $z\n"; 

my @z = ($x, $y); 
print "@z\n"; 

首先,我用warnings。因此,當我運行該腳本,我得到警告:

Useless use of private variable in void context at C:\Temp\t.pl line 7.

始終啓用警告。現在

,輸出顯示發生了什麼:

$x = HASH(0x39cbc)  $y = HASH(0x39dac)  $z = HASH(0x39dac) 
HASH(0x39cbc) HASH(0x39dac)

顯然,$z指的是相同的匿名哈希一樣$y。沒有值的複製完成。

而且,$z[0]指的是相同的匿名哈希一樣$x$z[1]指的是相同的匿名有因爲這樣做$y$z

請注意,圓括號本身不會創建列表上下文。在

my @z = ($x, $y); 

的情況下,他們是必要的,因爲=結合比逗號操作更加緊密。

my @z = $x, $y; 

將分配給$x$z[0]丟棄$y(併發出警告),而

my @z = 1 .. 5; 

會達到預期效果。

最後,如果你想分配給$z包含匿名散列的副本新的匿名哈希其中兩個$x$y點,你會做

#!/usr/bin/perl 
use strict; use warnings; 
use Data::Dumper; 

my $x = {a => 1}; 
my $y = {a => 2, b => 0}; 

my $z = { %$x, %$y }; 

print Dumper $z; 

這將輸出:

$VAR1 = { 
      'a' => 2, 
      'b' => 0 
     };

因爲根據定義,散列鍵是唯一的。如果你想保持與兩個哈希的鍵相關聯的所有值,你需要做一些稍微複雜(並在「聯盟」散列使用匿名arrayrefs作爲值):

#!/usr/bin/perl 
use strict; use warnings; 
use Data::Dumper; 

my $x = {a => 1}; 
my $y = {a => 2, b => 0}; 

my $z; 

push @{ $z->{$_} }, $x->{$_} for keys %$x; 
push @{ $z->{$_} }, $y->{$_} for keys %$y; 

print Dumper $z; 

輸出:

VAR1 = { 
     'a' => [ 
        1, 
        2 
       ], 
     'b' => [ 
        0 
       ] 
     };
+0

是的!就我所知,它實際上是在「做」別的東西。 – Don 2010-12-16 22:07:11

+1

認爲比較會更清楚。隨意糾正/回滾,如果我搞砸了 – 2010-12-16 22:13:07

+0

@bemace我認爲最好是澄清沒有底層匿名哈希的副本。 – 2010-12-16 22:37:54