Currying Patterns

One of the most dangerous books I’ve ever even partially read is MJD’s Higher Order Perl. In particular, its description of subroutine currying – that is, building more specific functions out of more general purpose ones – is a pattern I find incredibly useful.

The other day I found myself writing a number of routines that were surprisingly similar… kinda. They all implemented a common pattern, but across routines that were rather… different. I found myself wistfully longing for the familiar pattern of currying, and then realized – I’m working in PERL, DAMNIT.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
sub validate_thing { _validate_subtest_wrapper(\&_validate_thing_guts, @_) }
sub validate_class { _validate_subtest_wrapper(\&_validate_class_guts, @_) }
sub validate_role { _validate_subtest_wrapper(\&_validate_role_guts, @_) }

sub _validate_subtest_wrapper {
  my ($func, $func, $func, $thing, %args) = @_;

  # note incrementing by 2 because of our upper curried function
  local $Test::Builder::Level = $Test::Builder::Level + 2;

  # run tests w/o a subtest wrapper...
  return $func->($thing => %args)
    unless $args{-subtest};

  # ...or with one.
  return $tb->subtest(delete $args{-subtest} => sub { $func->($thing => %args) });
}

This is part of recent work of mine, extending Test::Moose::More to use subtests where they make sense. Here I was able to curry one function – _validate_subtest_wrapper() – by passing it a reference to another function, that it then invokes.

Excellent. Life is easier, as it should be.

0%