"Can't modify non-lvalue subroutine call" 从方法中添加 Moose 属性时
"Can't modify non-lvalue subroutine call" when adding Moose attribute from method
我这几天,我运行遇到了下面的问题。我创建了一个对象,该对象在创建时具有许多必需的属性。但是,我希望在调用方法时向其添加属性。更具体地说,我想将该方法的参数添加为散列属性。我想这样做,以便后续对其他方法的调用知道已经使用所述参数调用了较早的方法。
示例,但代码是虚构的:
package Banana;
use Moose;
has ['peel', 'edible'] => (
is => 'ro',
isa => 'Bool',
required => 1,
);
has 'color' => (
is => 'ro',
isa => 'Str',
required => 1,
);
has 'grow_params' => (
is => 'ro',
isa => 'HashRef',
);
sub grow {
my ($self, $params) = @_;
# params would be a hashref of method arguments
$self->grow_params = $params;
# Execute some code changing other, initial vars
}
这行不通,因为会抛出以下错误:
Can't modify non-lvalue subroutine call of &Banana::grow_params
我在这里查看了 SO 和 PerlMonks,但我似乎无法找到错误 的含义 的一般解释。大多数答案只是重写原始代码,仅此而已。那么这个错误是什么意思,我能完成我想做的事情吗?还是这不是方法?
Moose 对象属性隐藏在同名函数后面,因此当您拥有 $self->grow_params
时,它就是一个函数。试图给它赋值是行不通的,你需要像函数一样调用它。
$self->grow_params($params);
但即便如此,由于您目前已将 grow_params 定义为只读,因此一旦创建了对象,您就无法更改它的值,即使是在它自己的方法中也是如此。
进一步解释错误的含义...
一个基本的赋值语句如下所示:
$variable = 'value';
运算符 ($variable
) 左侧的操作数是一个 "lvalue"。运算符 ('value'
) 右侧的操作数是 "rvalue".
在上面的简单示例中,右值是一个简单的常量,但我希望您意识到它也可以是另一个变量:
$variable = $some_other_variable;
甚至表达式的结果:
$variable = 2 * $pi * $radius ** 2;
但是您知道(至少本能地)左值必须是一个变量。你知道这样的代码毫无意义:
'value' = $variable;
Moose 属性访问器和修改器("getters" 和 "setters")只是子例程。子程序通常是右值。这意味着您不能(通常)分配这样的属性:
$obj->attribute = 'value';
您需要将新值传递给方法:
$obj->attribute('value');
但是,有一个名为 MooseX::LvalueAttribute 的 Moose 扩展,它允许您定义左值增变器方法,这些方法完全按照您的原始代码预期的方式工作。不过我真的不推荐它,因为这不是维护程序员希望在您的代码中看到的内容。
我这几天
示例,但代码是虚构的:
package Banana;
use Moose;
has ['peel', 'edible'] => (
is => 'ro',
isa => 'Bool',
required => 1,
);
has 'color' => (
is => 'ro',
isa => 'Str',
required => 1,
);
has 'grow_params' => (
is => 'ro',
isa => 'HashRef',
);
sub grow {
my ($self, $params) = @_;
# params would be a hashref of method arguments
$self->grow_params = $params;
# Execute some code changing other, initial vars
}
这行不通,因为会抛出以下错误:
Can't modify non-lvalue subroutine call of
&Banana::grow_params
我在这里查看了 SO 和 PerlMonks,但我似乎无法找到错误 的含义 的一般解释。大多数答案只是重写原始代码,仅此而已。那么这个错误是什么意思,我能完成我想做的事情吗?还是这不是方法?
Moose 对象属性隐藏在同名函数后面,因此当您拥有 $self->grow_params
时,它就是一个函数。试图给它赋值是行不通的,你需要像函数一样调用它。
$self->grow_params($params);
但即便如此,由于您目前已将 grow_params 定义为只读,因此一旦创建了对象,您就无法更改它的值,即使是在它自己的方法中也是如此。
进一步解释错误的含义...
一个基本的赋值语句如下所示:
$variable = 'value';
运算符 ($variable
) 左侧的操作数是一个 "lvalue"。运算符 ('value'
) 右侧的操作数是 "rvalue".
在上面的简单示例中,右值是一个简单的常量,但我希望您意识到它也可以是另一个变量:
$variable = $some_other_variable;
甚至表达式的结果:
$variable = 2 * $pi * $radius ** 2;
但是您知道(至少本能地)左值必须是一个变量。你知道这样的代码毫无意义:
'value' = $variable;
Moose 属性访问器和修改器("getters" 和 "setters")只是子例程。子程序通常是右值。这意味着您不能(通常)分配这样的属性:
$obj->attribute = 'value';
您需要将新值传递给方法:
$obj->attribute('value');
但是,有一个名为 MooseX::LvalueAttribute 的 Moose 扩展,它允许您定义左值增变器方法,这些方法完全按照您的原始代码预期的方式工作。不过我真的不推荐它,因为这不是维护程序员希望在您的代码中看到的内容。