以下是我的代码(不要担心模块顶部有USUW)
我正在测试数组ref是否只读,如果是这种情况,那么我将它复制到另一个数组ref。测试显示该数组不是只读的,但是当它运行时,它会因该错误而失败。 (对于那些不熟悉我或Smart::Comments
的人 - 那些###
是Smart::Comments
。
### readonly( $arg_ref ) : readonly( $arg_ref )
### readonly( @$arg_ref ) : readonly( @$arg_ref )
my @ro = map { readonly( $_ ) } @$arg_ref;
### @ro
if ( readonly $arg_ref ) {
$arg_ref = [ @$arg_ref ];
}
return map { my $val = shift @$arg_ref;
$_ => $val
} @_
;
这是我得到的输出:
### readonly( $arg_ref ) : 0
### readonly( @$arg_ref ) : 0
### @ro: [
### 0,
### 0,
### 0,
### 0,
### 0
### ]
但这是错误:
Modification of a read-only value attempted at ....pm line 247.
(247是:
return map { my $val = shift @$arg_ref;
)
有人对此问题有任何熟悉吗?我们正在运行Perl 5.8.7。关于如何解决它的任何想法?
答案 0 :(得分:2)
如果来自DBI::fetchrow_arrayref
的引用以只读方式返回,则尝试覆盖它将无济于事:引用是只读的,而不是东西( ie ,具有列值的数组。)
如果您需要破坏性更新,请在源代码制作您自己的副本,例如,
my $arg_ref = [ $sth->fetchrow_array ];
答案 1 :(得分:1)
Readonly和readonly是不同的。 (注意大写R和小写r。;-))
请参阅Scalar::Util文档了解其原因:
readonly SCALAR
如果SCALAR是只读的,则返回true。
sub foo { readonly($_[0]) } $readonly = foo($bar); # false $readonly = foo(0); # true
这更多是关于别名(例如通过foreach循环或@_
传入的别名,而不是Readonly模块。
答案 2 :(得分:1)
我想我已经弄清楚了。 Robert P是对的,但他只得到了答案的一半:Readonly
和readonly
做了不同的事情,尽管他们应该做同样的事情,事实上他们不是一个错误。我会试着解释发生了什么。
Readonly
有两个标量实现:一个(Readonly::XS)基于SvREADONLY
标志,一个(Readonly :: Scalar)基于模仿{{1国旗。
SvREADONLY
也有两个实现,一个在Perl中(它执行自我赋值并检查它是否抛出异常),一个在XS中(同样基于readonly
标志)。 / p>
有4种可能的组合,不幸的是,最常见的组合(纯perl Readonly和XS只读)是唯一不能像宣传的那样工作的组合。
以下是关键:SvREADONLY
实际上根本不使用sub Readonly::Readonly
,只有Readonly::XS
。 这可能是个错误。 sub Readonly::Scalar
正确报告该变量不是一个只读变量:它的readonlyness是由一个平局伪造的。
这是readonly
IMO的错误,它应该做正确的事情,并在不能的时候记录。现在它正在做这两件事。
答案 3 :(得分:0)
看起来Scalar::Util::readonly的结果可能是 trusted 使用了你想要的方式。证人:
perl -MScalar::Util=readonly -MReadonly -wle'
Readonly my $arg_ref => [ qw(a b c)];
print readonly $arg_ref;
$arg_ref = 1;'
打印:
0
Modification of a read-only value attempted at -e line 1.
(使用Readonly 1.03,Scalar :: Util 1.23在perl5.8.8下测试)