7

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.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
skiphoppy
  • 97,646
  • 72
  • 174
  • 218

3 Answers3

14

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.

rjbs
  • 1,327
  • 11
  • 18
10

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?

Dave Rolsky
  • 4,524
  • 1
  • 24
  • 24
  • Well, I know it isn't a reference in the Perl sense; I was just thinking better programming practice would be to pass a real reference to a named subroutine, for the reasons I mentioned. However, you're right; the rest of the manual does show why the way it is is desirable ... – skiphoppy Feb 18 '09 at 16:34
  • 1
    Note the paragraph that begins "This has several advantages. First..."; maybe it would help to move some of the next section up there to follow up so the paragraph gives more than just that one advantage, a little sooner for those who are wondering. – skiphoppy Feb 18 '09 at 16:36
7

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.

jrockway
  • 42,082
  • 9
  • 61
  • 86