1

I have a set of methods where I would like the caller to be able to override a value, or it defaults to the instance variable.

So what I keep trying to do is:

method foo( Str :$blah = $self->blah ) {
    #doStuff
}

which throws a parsing error so I end up doing this everywhere

method foo( Str :$blah? ) {
    $blah = $self->blah unless defined $blah;
    #doStuff
}

Not horrendous, but seems silly when MooseX::Method::Signatures supports the default concept and has fixed all my other standard 'start of method' lines.

Invariably when I'm trying to do something like this and I can't find anyone else on the web who's run into the same problems, I'm approaching the problem the wrong way. It seems like I might be trying to jam a functional program into a oo layout, rather than actual oo as the methods are more helper functions for calling externally rather than methods operating on the object. So just checking if I'm just defining it incorrectly or if what I'm doing is "dumb" or just not supported by Parse::Method::Signatures.

Matt
  • 68,711
  • 7
  • 155
  • 158

1 Answers1

1

AFAIK The Signatures module hooks itself into the Perl parser and injects some code to handle the prototypes. It is remarkable that this works.

That said, using non-constant values as defaults could have issues. And there may be scenarios where calling some code to prepopulate a value could wreak havoc. Specifically, should the code that prepopulates the value should only be called if no value for the argument is given, or should it be always called? What should we do with side effects? What should the caller be? If I have a global $self object, shouldn't that receive the method call, as the scoping rules clearly dictate this? (As our $x=5; my $x=$x; is valid, but just my $x=$x is not). Even better, what would happen if the default value population method call would call the same method, but again without a value for the optional parameter?

You can always fall back to old-school optional parameters:

sub foo {
  my ($self, $blah) = @_;
  # something like my ($self, $blah) = (@_, $self->blah); wouldn't work, of course.
  $blah //= $self->blah; # nicer than old `unless defined`
  ...;
}

or, in this case:

method foo (:$blah?) {
   $blah //= $self->blah
}

I find this use of the defined-or operator quite enjoyable.

amon
  • 57,091
  • 2
  • 89
  • 149
  • I see where you're going with the non constant values stuff. In my head I was expecting the call to work just as the `unless defined` or `//=` code would. This being based on the assumption, which could be entirely baseless, that the method signatures are parsed into the subs they represent and injected and that it would leave $self alone for the actual method call. Might be time to poke around the sources and see what it actually does. Thanks for the defined-or tip, hadn't seen that one before. – Matt Dec 05 '12 at 14:49