Use subroutine signatures with anonymous subroutines

While working on my excellent number project, I created a subroutine that took a callback as an argument. When I dereferenced the callback I wanted to supply arguments. Since I was using Perl v5.22, I tried using a subroutine signature with it.

my $max_a = bisect(
	sub ( $a, $k ) { sqrt( $a * 10**$k + $a**2 ) },
	my $threshold = 1

I had no reason to think that it wouldn’t work but the idea hadn’t occurred to me when I wrote about subroutine signatures as a new feature in v5.20. The section on “Signatures” in perlsub doesn’t have an example with an anonymous subroutine. And it works. But, maybe it’s not supposed to. This is an experimental feature and it is undocumented, but I hope it sticks around.

Consider what I would have to write without the signatures. I could assign the arguments myself:

sub { my( $a, $k ) = @_; sqrt( $a * 10**$k + $a**2 ) }

This is different than the signatures, though. I don’t check the number of arguments, possibly set defaults, and many other niggling tasks I don’t like re-typing.

I could also use the elements in @_ directly:

sub { sqrt( $_[0] * 10**$_[1] + $_[0]**2 ) }

That is ugly in even a way a staunch Perler will admit, and I know that single-element access to Perl special arrays tends to throw off newbies. I’m guilty of this because I haven’t had a prettier alternative that I’ve seen in other languages:

import math
lambda a, k: math.sqrt( a * 10**k + a**2 )
# ruby
lambda { |a, k| Math.sqrt(a * 10**k + a**2) }
# smalltalk
[ :a :k | (a * (10 raisedTo: k) + a squared) sqrt ]

Perl 6 has the pointy block syntax along with other cool ways to create fancy subroutines:

# perl6
-> $a, $k { sqrt($a * 10**$k + $a**2) };

Now that I have this syntax in Perl, even if it is experimental, I know that I’m going to abuse it and come to rely on it.

One thought on “Use subroutine signatures with anonymous subroutines”

  1. Signatures on anonymous subs are great, and I use them all the time. They definitely won’t be going away. We’ve got tests for them, and I’ve just added a commit to mention that they work — thanks for pointing out that it wasn’t documented!

Comments are closed.