Friday, September 18, 2009

Method Style Callbacks

This is a small trick I like to use when defining callbacks. Instead of invoking callbacks as code references:

$callback->($data);

I always write the invocation as a method call:

$data->$callback();

or if $data is not a natural invocant for the routine, then I invoke it as a method on the object that is sending the notification:

$self->$callback($data);

This works in more cases than just plain code reference invocation:

  • If $data is an object then $callback can be a string (a method name).
  • If $callback is a code reference there is no difference between this syntax and code dereferncing
  • Even if $data is not an object but $callback is a code reference, the method syntax will still work.

It's pretty nice to be able to pass method names as callbacks invoked on a subclass but still have the flexibility of a code reference when appropriate, and works especially well when the callback attribute has a sensible default value that resolves to a method call on $self to allow easy overriding of behavior without needing a full subclass.

2 comments:

dami said...

Very interesting. I had never seen this $data->$coderef() notation before (when $data is not an object); but indeed it works! However, I couldn't find any mention of it in perldoc. So is this an undocumented side-effect of the current implementation, or is it really a Perl feature ?

nothingmuch said...

I think it's a side effect of the implementation.

Method calls are two opcodes, one opcode to find a code ref, and then a normal subroutine invocation.

The "method" opcode will simply do nothing if a the method being invoked is already a code reference and the "entersub" opcode doesn't really care what the arguments to the code ref are.

BTW, the way that autobox works is by overriding the definition of that opcode in a lexical scope making method calls on non objects no longer be an error.