2014-10-26 66 views
1

我碰到這個,找不到答案。我試圖看看是否有可能「改變」散列的引用。換句話說,我有一個散列函數和一個返回hashref的函數,並且我想讓我的散列點指向由此ref指定的內存中的位置,而不是複製它指向的散列的內容。該代碼看起來是這樣的:perl變更引用散列

%hash = $h->hashref; 

我明顯的猜測是,它應該是這樣的:

\%hash = $h->hashref; 

但提供了錯誤:

Can't modify reference constructor in scalar assignment

我嘗試了一些其他事情,但沒有奏效。我正在嘗試實際上可能嗎?

+0

不幸的是我不知道PHP中的引用如何表現,所以我不確定。 – insaner 2014-10-26 16:08:26

+0

'$ h-> hashref'是一個返回散列引用的對象中的函數。具體來說,它是dbi函數'$ sth-> fetchrow_hashref',但我不想讓人們誤以爲這個問題是關於dbi的。 – insaner 2014-10-26 16:12:30

+0

這將取消引用hashref(並將值複製到%hash),所以它與我想要的相反。 – insaner 2014-10-26 16:15:43

回答

1

聽起來像是你想:

use Data::Alias; 
alias %hash = $h->hashref; 

,或者散列%是包變量,則可以僅做:

*hash = $h->hashref; 

但無論哪種方式,這應該總是儘量避免;你爲什麼不簡單地使用哈希引用?

+0

感謝您的回答!爲了回答你的問題,我只是寫了一些已經使用散列的代碼,所以我試圖這樣做,只是因爲我認爲這是可能的(而不是問題)。我可能會訴諸使用refs作爲我的解決方案。再次感謝 – insaner 2014-10-26 17:22:00

1

是的,但...

perl中的引用是標量。你試圖實現的是別名返回值。這實際上是可能的,但你應該而不是這樣做,因爲它涉及符號表的混亂。此外,這種只爲全局作品(聲明與我們的):如果您分配一個hashref的水珠*hash將分配給符號表項%hash

#!/usr/bin/env perl 

use warnings; 
use strict; 

sub a_hashref{{a => "one", b => "two"}} 

our %hash; 
*hash = a_hashref; 

printf "%3s -> %s\n",$_,$hash{$_} foreach keys %hash; 

這是不好的風格!它不在PBP中(直接,但請考慮第5.1節:「避免非詞彙表」),並且不會被perlcritic報告,但是您不應該污染軟件包名稱空間以獲得一些語法幻想。此外,它不適用於詞法變量(這是你可能想要使用的大部分時間,因爲它們是詞彙範圍的,而不是包寬的)。另一個問題是,如果$h->hashref方法更改其返回類型,您將突然分配給另一個表條目! (因此,如果$h->hashref將其返回類型更改爲arrayref,則將其分配給@hash,祝您好運)。你可以通過檢查$h->hashref是否確實返回一個帶有'HASH' eq ref $ h-> hashref`的hashref來避開這種情況,但這樣會破壞目的。

只是保持參考的問題是什麼?如果你得到一個參考,爲什麼不把它存儲在一個標量?

$哈希= $ H-> hashref

要了解更多有關全局符號表看看perlmod並考慮perlref*FOO{THING}語法,這可悲的不是左值。

爲了實現你想要的,你可以看看幾個別名modules on cpanData::AliasLexical::Alias似乎適合您的目的。另外,如果您對tie語義感興趣並且/或者不想使用XS模塊,則Tie::Alias可能值得拍攝。

+0

感謝您的答案!要回答你的問題,我只是寫了一些代碼,並試圖做到這一點,只是因爲我認爲這是可能的(而不是不平凡或有問題)。我可能會訴諸使用refs作爲我的解決方案。再次感謝 – insaner 2014-10-26 17:20:44

+1

@Insaner:好的,但是如果你想辜負你的用戶名,你應該儘可能多地使用它們。如果其他人可能想要使用他們的代碼,那麼可能不會。我添加了一個模塊部分,你可以考慮其中的一部分,因爲它只增加了兩行代碼(和一些安裝,但是'cpanm'目前只有一個命令) – 2014-10-26 17:29:56

1

這是一個實驗性功能,它看起來可以讓您正確地描述has been added到Perl 5.21.5,它是一個開發版本(請參閱「通過引用混淆」)。