Rubyでチャーチ数

Rubyに慣れるとっかかりとしてチャーチ数を定義してみた。
lambdaで包まずに関数リファレンスを関数に渡す方法がわからない。。

# 数値(xに対するs関数の適用回数で数値を表す)
def zero  (s, x) x end 
def one   (s, x) s[x] end 
def two   (s, x) s[s[x]] end 
def three (s, x) s[s[s[x]]] end 
def four  (s, x) s[s[s[s[x]]]] end 
def five  (s, x) s[s[s[s[s[x]]]]] end 

# 足し算(m+n回だけxに対してs関数を適用する)
def plus(m, n, s, x)
  m[s, n[s, x]] 
end
n = plus(
  lambda{|s, x| five(s, x)}, 
  lambda{|s, x| two(s, x)}, 
  lambda{|n| n + 1}, 0)
print "5 + 2 = ", n, "\n"

# 掛け算(m*n回だけxに対してs関数を適用する)
def multi(m, n, s, x)
  m[lambda{lambda{|x| n[s, x]}}.call(), x]
end
m = multi(
  lambda{|s, x| four(s, x)},
  lambda{|s, x| three(s, x)},
  lambda{|n| n + 1}, 0)
print "4 * 3 = ", m, "\n"

実行すると次のようになる。

5 + 2 = 7
4 * 3 = 12

まったく同じことをPerlでも。

#! /usr/bin/perl
use strict;
use warnings;

# 数値($xに対する$s関数の適用回数で数値を表す)
sub zero  { my ($s, $x) = @_; $x; }
sub one   { my ($s, $x) = @_; $s->($x); }
sub two   { my ($s, $x) = @_; $s->($s->($x)); }
sub three { my ($s, $x) = @_; $s->($s->($s->($x))); }
sub four  { my ($s, $x) = @_; $s->($s->($s->($s->($x)))); }
sub five  { my ($s, $x) = @_; $s->($s->($s->($s->($s->($x))))); }

# 足し算($m+$n回だけ$xに対して$s関数を適用する)
sub plus {
  my ($m, $n, $s, $x) = @_; 
  $m->($s, $n->($s, $x));
}
my $n = plus(\&five, \&two, sub { ++$_[0] }, 0); 
print "5 + 2 = ", $n, "\n";

# 掛け算($m*$n回だけ$xに対して$s関数を適用する)
sub multi {
  my ($m, $n, $s, $x) = @_; 
  $m->(
    sub { sub { my ($x) = @_; $n->($s, $x) } }->(),
    $x
  );
}
my $m = multi(\&four, \&three, sub { ++$_[0] }, 0); 

Rubyの方が簡潔っぽい。