perl变更引用散列

问题描述:

我碰到这个,找不到答案。我试图看看是否有可能“改变”散列的引用。换句话说,我有一个散列函数和一个返回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

听起来像是你想:

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

,或者散列%是包变量,则可以仅做:

*hash = $h->hashref; 

但无论哪种方式,这应该总是尽量避免;你为什么不简单地使用哈希引用?

+0

感谢您的回答!为了回答你的问题,我只是写了一些已经使用散列的代码,所以我试图这样做,只是因为我认为这是可能的(而不是问题)。我可能会诉诸使用refs作为我的解决方案。再次感谢 – insaner 2014-10-26 17:22:00

是的,但...

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

这是一个实验性功能,它看起来可以让您正确地描述has been added到Perl 5.21.5,它是一个开发版本(请参阅“通过引用混淆”)。