Writing recursive closures
I discovered the other day that you can do quite horrifying things with perl. A closure in perl is a nice concept - it’s a block that can reference things in the scope that it’s declared in, but that can be passed around and used in quite different scopes. For instance, suppose I wanted a function that, say, converted a string to utf8 bytes (yes, I’m obsessed with utf8). I can do this like this:
my $closure;
$closure = sub {
my $val = shift;
return Encode::encode("utf8", $val);
};
And call it later as:
print $closure->("héllo");
This is dead nifty. But because a closure can reference things in it’s scope, and $closure is in it’s scope, it can call itself, or at least, it can call the function pointed at by $closure. So we can make this function recursive:
$closure = sub {
my $val = shift;
if (ref $val eq "ARRAY") {
return [ map { $closure->($_) } @$val ];
} elsif (ref $val eq "HASH") {
return { map { $_ => $closure->($_) } keys(%$val) };
} else {
return Encode::encode("utf8", $val);
}
};
Until the assignment is complete, the inside of the closure won’t work, because $closure is undefined. But by the time we call it later..
return $closure->( [ "héllo", { foo =>"bår" } ] );
..everything works.
Crazy, I tell you.