I am battling with Moose these days, and I ran into the following problem. I create an object that has many required attributes on its creation. However, I wish to add attributes to it when a method is called. More specifically, I'd like to add the arguments for that method as a hash attribute. I'd like to do this so that subsequent calls to other methods know that the earlier method has already been called, with said parameters.
Example, but fictional code:
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
}
This won't work, as the following error gets thrown:
Can't modify non-lvalue subroutine call of
&Banana::grow_params
I've looked here on SO and on PerlMonks but I can't seem to find a general explanation of what the error means. Most answers simply re-write the original code and that's that. So what does the error mean, and can I accomplish what I'm trying to do? Or is this not the way to do it?
To explain a little more about what the error means...
A basic assignment statement looks like this:
$variable = 'value';
The operand to the left of the operator ($variable
) is an "lvalue". The operand to the right of the operator ('value'
) is an "rvalue".
In the simple example above, the rvalue is a simple constant, but I hope you realise that it could also be another variable:
$variable = $some_other_variable;
or even the result of an expression:
$variable = 2 * $pi * $radius ** 2;
But you know (instinctively, at least) that the lvalue has to be a variable. You know that code like this makes no sense:
'value' = $variable;
Moose attribute accessors and mutators (the "getters" and "setters") are just subroutines. And subroutines are usually rvalues. This means that you can't (usually) assign an attribute like this:
$obj->attribute = 'value';
You would need to pass the new value to the method:
$obj->attribute('value');
However, there is a Moose extension called MooseX::LvalueAttribute which allows you to define lvalue mutator methods that work exactly how your original code expected them to. I really don't recommend it though, as it's not what maintenance programmers will expect to see in your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With