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の方が簡潔っぽい。