$IF = sub { my $b = shift; sub { my $t = shift; sub { my $f = shift; ($b)->($t)->($f); } } } ; $TRUE = sub { my $x = shift; sub { my $y = shift; $x; } } ; $FALSE = sub { my $x = shift; sub { my $y = shift; $y; } } ; $PAIR = sub { my $x = shift; sub { my $y = shift; sub { my $b = shift; ($b)->($x)->($y); } } } ; $FIRST = sub { my $p = shift; ($p)->($TRUE); } ; $SECOND = sub { my $p = shift; ($p)->($FALSE); } ; $ZERO = ($PAIR)->($TRUE)->($TRUE); $SUCC = sub { my $n = shift; ($PAIR)->($FALSE)->($n); } ; $ONE = ($SUCC)->($ZERO); $TWO = ($SUCC)->($ONE); $IS_ZERO = sub { my $n = shift; ($FIRST)->($n); } ; $PRED = sub { my $n = shift; ($SECOND)->($n); } ; sub convert_to_perl_number { my $n = shift; return "OOPS($n)" unless ref $n eq 'CODE'; my $o = 0; until ($IF->($IS_ZERO->($n))->(1)->(undef)) { $o++; $n = $PRED->($n); } $o; } sub print_number { print "If this is a number, its value is ", convert_to_perl_number(shift()), "\n" ; } # This doesn't work because of Perl's call-by-value semantics $Y = sub { my $f = shift; (sub { my $x = shift; ($f)->(($x)->($x)); })->(sub { my $x = shift; ($f)->(($x)->($x)); }); }; # Use this one instead: $YV = sub { my $f = shift; (sub { my $x = shift; sub { my $y = shift; $f->($x->($x)); }; })-> (sub { my $x = shift; sub { my $y = shift; $f->($x->($x)); }; }) } ; $FORCE = sub { my $x = shift; $x }; $R = sub { my $g = shift; sub { my $m = shift; sub { my $n = shift; $IF->($IS_ZERO->($m)) ->(sub { my $q = shift; $n} ) ->(sub { my $q = shift; ($g->($FORCE))->($PRED->($m))->($SUCC->($n)); })->($FORCE); } } } ; $S = sub { my $g = shift; sub { my $m = shift; sub { my $n = shift; $IF->($IS_ZERO->($m)) ->(sub { my $q = shift; $ZERO} ) ->(sub { my $q = shift; $ADD->($n)->($g->($PRED->($m))->($n)) })->($FORCE); } } } ; # Yes, this actually constructs the addition function $ADD = $YV->($R)->($FORCE); $MUL = $YV->($S)->($FORCE); 1; $mystery_result = $MUL->($TWO)->($TWO); print_number $mystery_result;