lvalue子程序引用能否作为lvalue使用?Perl代码报错求助
Perl中通过子程序引用调用lvalue方法赋值失败的原因及解决办法
你的问题核心是:调用lvalue方法的代码引用时,没有传递对象实例作为参数,导致赋值操作没有作用到目标对象上,反而触发了无用赋值的警告。
问题分析
- 当你用
$self->can($method)获取到lvalue方法的代码引用后,直接调用$sub->()时,Perl不会自动把$self作为第一个参数传递给这个子程序。这就导致lvalue方法里的$_[0]是空值,$_[0]->[1]根本无法访问到对象的数组元素,赋值操作只是给一个临时返回值做了无用操作,所以出现Useless assignment to a temporary警告,最终对象的boff属性没有被初始化。 - 而
$self->$method = $value这种语法是Perl标准的方法调用,Perl会自动将$self作为第一个参数传入方法,所以lvalue方法能正确操作对象的内部数据,赋值生效。
解决办法
调用代码引用时,手动将$self作为第一个参数传递进去,修改Warning包的initbyname方法中调用代码引用的部分:
# 原错误代码 # $sub->() = $value # 修改为 $sub->($self) = $value
修改后的完整Warning包initbyname方法:
sub initbyname { my $self = shift; $self = $self->new unless ref $self; carp "'Warning' object already initialized" if @$self; while (@_) { my $method = shift; my $value = shift; my $sub = $self->can($method); $sub ? ( $sub->($self) = $value ) : ( carp "method '$method' not found" ); } return $self; }
验证效果
修改后运行代码,会得到预期输出:
warning->boff = 12 thisworks->roff = 13
这种用法是完全可行的,只是你之前忽略了Perl方法调用的本质——子程序调用会自动传递调用者作为第一个参数,手动调用代码引用时必须自己补上这个参数。
内容的提问来源于stack exchange,提问作者FreonPSandoz
相关产品推荐
相关产品推荐

