Reputation: 102793
Moose::Manual::Attributes states:
As an alternative to using a subroutine reference [for default], you can instead supply a builder method for your attribute: ... This has several advantages. First, it moves a chunk of code to its own named method, which improves readability and code organization.
So, your attribute could define a default thusly:
has attr => (
is => 'ro',
builder => 'subroutine'
);
sub subroutine {
# figure out and return default value
}
I don't get why this has to be separate from default. Couldn't you just pass a reference to a named subroutine?
has attr => (
is => 'ro',
default => \&subroutine
);
And would that not be better programming practice, since you're guaranteed not to accidentally refer to a subroutine that doesn't exist? You'd be referring to the method with a logical reference instead of a symbolic reference.
Upvotes: 7
Views: 737
Reputation:
Subclassing.
Builder specifies a method name to call, so
package Something;
use Moose;
extends 'YourClass';
sub subroutine { <some other default> }
would have Something::subroutine called for a builder of 'subroutine', whereas if you used the subref style then the YourClass::subroutine would be called instead because you've made a direct reference to the subroutine rather than letting it go through method dispatch.
Upvotes: 7
Reputation: 1327
When the builder is called, this happens:
$object->$builder
If builder is a string (let's say build_attr
), then users can write their own build_attr method in a subclass and it will be called. This makes the default value extensible via a simple named method mechanism.
If it's a reference to a subroutine, the reference is taken in the original class's package, which means it can't be overriden the same way.
Upvotes: 14
Reputation: 4532
It's not a "symbolic" reference. The builder is a method name. That means it is inheritable and composable from a role. If you pass a subroutine reference, that reference must exist in the same package (or be fully qualified).
I'm pretty sure I explain this in the manual. Is it unclear?
Upvotes: 10