Y combinator

From Rosetta Code
Jump to: navigation, search
Task
Y combinator
You are encouraged to solve this task according to the task description, using any language you may know.

In strict functional programming and the lambda calculus, functions (lambda expressions) don't have state and are only allowed to refer to arguments of enclosing functions. This rules out the usual definition of a recursive function wherein a function is associated with the state of a variable and this variable's state is used in the body of the function.

The Y combinator is itself a stateless function that, when applied to another stateless function, returns a recursive version of the function. The Y combinator is the simplest of the class of such functions, called fixed-point combinators.

The task is to define the stateless Y combinator and use it to compute factorials and Fibonacci numbers from other stateless functions or lambda expressions.

Cf

Contents

[edit] ALGOL 68

Translation of: Python
Note: This specimen retains the original Python coding style.
Works with: ALGOL 68S version from Amsterdam Compiler Kit ( Guido van Rossum's teething ring) with runtime scope checking turned off.
BEGIN
MODE F = PROC(INT)INT;
MODE Y = PROC(Y)F;
 
# compare python Y = lambda f: (lambda x: x(x)) (lambda y: f( lambda *args: y(y)(*args)))#
PROC y = (PROC(F)F f)F: ( (Y x)F: x(x)) ( (Y z)F: f((INT arg )INT: z(z)( arg )));
 
PROC fib = (F f)F: (INT n)INT: CASE n IN n,n OUT f(n-1) + f(n-2) ESAC;
 
FOR i TO 10 DO print(y(fib)(i)) OD
END

[edit] AppleScript

AppleScript is not terribly "functional" friendly. However, it is capable enough to support the Y combinator.

AppleScript does not have anonymous functions, but it does have anonymous objects. The code below implements the latter with the former (using a handler (i.e. function) named 'funcall' in each anonymous object).

Unfortunately, an anonymous object can only be created in its own statement ('script'...'end script' can not be in an expression). Thus, we have to apply Y to the automatic 'result' variable that holds the value of the previous statement.

The identifier used for Y uses "pipe quoting" to make it obviously distinct from the y used inside the definition.

to |Y|(f)
script x
to funcall(y)
script
to funcall(arg)
y's funcall(y)'s funcall(arg)
end funcall
end script
f's funcall(result)
end funcall
end script
x's funcall(x)
end |Y|
 
script
to funcall(f)
script
to funcall(n)
if n = 0 then return 1
n * (f's funcall(n - 1))
end funcall
end script
end funcall
end script
set fact to |Y|(result)
 
script
to funcall(f)
script
to funcall(n)
if n = 0 then return 0
if n = 1 then return 1
(f's funcall(n - 2)) + (f's funcall(n - 1))
end funcall
end script
end funcall
end script
set fib to |Y|(result)
 
set facts to {}
repeat with i from 0 to 11
set end of facts to fact's funcall(i)
end repeat
 
set fibs to {}
repeat with i from 0 to 20
set end of fibs to fib's funcall(i)
end repeat
 
{facts:facts, fibs:fibs}
(*
{facts:{1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800},
fibs:{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765}}
*)

[edit] BlitzMax

BlitzMax doesn't support anonymous functions or classes, so everything needs to be explicitly named.

SuperStrict
 
'Boxed type so we can just use object arrays for argument lists
Type Integer
Field val:Int
Function Make:Integer(_val:Int)
Local i:Integer = New Integer
i.val = _val
Return i
End Function
End Type
 
 
'Higher-order function type - just a procedure attached to a scope
Type Func Abstract
Method apply:Object(args:Object[]) Abstract
End Type
 
'Function definitions - extend with fields as locals and implement apply as body
Type Scope Extends Func Abstract
Field env:Scope
 
'Constructor - bind an environment to a procedure
Function lambda:Scope(env:Scope) Abstract
 
Method _init:Scope(_env:Scope) 'Helper to keep constructors small
env = _env ; Return Self
End Method
End Type
 
 
'Based on the following definition:
'(define (Y f)
' (let ((_r (lambda (r) (f (lambda a (apply (r r) a))))))
' (_r _r)))
 
'Y (outer)
Type Y Extends Scope
Field f:Func 'Parameter - gets closed over
 
Function lambda:Scope(env:Scope) 'Necessary due to highly limited constructor syntax
Return (New Y)._init(env)
End Function
 
Method apply:Func(args:Object[])
f = Func(args[0])
Local _r:Func = YInner1.lambda(Self)
Return Func(_r.apply([_r]))
End Method
End Type
 
'First lambda within Y
Type YInner1 Extends Scope
Field r:Func 'Parameter - gets closed over
 
Function lambda:Scope(env:Scope)
Return (New YInner1)._init(env)
End Function
 
Method apply:Func(args:Object[])
r = Func(args[0])
Return Func(Y(env).f.apply([YInner2.lambda(Self)]))
End Method
End Type
 
'Second lambda within Y
Type YInner2 Extends Scope
Field a:Object[] 'Parameter - not really needed, but good for clarity
 
Function lambda:Scope(env:Scope)
Return (New YInner2)._init(env)
End Function
 
Method apply:Object(args:Object[])
a = args
Local r:Func = YInner1(env).r
Return Func(r.apply([r])).apply(a)
End Method
End Type
 
 
'Based on the following definition:
'(define fac (Y (lambda (f)
' (lambda (x)
' (if (<= x 0) 1 (* x (f (- x 1)))))))
 
Type FacL1 Extends Scope
Field f:Func 'Parameter - gets closed over
 
Function lambda:Scope(env:Scope)
Return (New FacL1)._init(env)
End Function
 
Method apply:Object(args:Object[])
f = Func(args[0])
Return FacL2.lambda(Self)
End Method
End Type
 
Type FacL2 Extends Scope
Function lambda:Scope(env:Scope)
Return (New FacL2)._init(env)
End Function
 
Method apply:Object(args:Object[])
Local x:Int = Integer(args[0]).val
If x <= 0 Then Return Integer.Make(1) ; Else Return Integer.Make(x * Integer(FacL1(env).f.apply([Integer.Make(x - 1)])).val)
End Method
End Type
 
 
'Based on the following definition:
'(define fib (Y (lambda (f)
' (lambda (x)
' (if (< x 2) x (+ (f (- x 1)) (f (- x 2)))))))
 
Type FibL1 Extends Scope
Field f:Func 'Parameter - gets closed over
 
Function lambda:Scope(env:Scope)
Return (New FibL1)._init(env)
End Function
 
Method apply:Object(args:Object[])
f = Func(args[0])
Return FibL2.lambda(Self)
End Method
End Type
 
Type FibL2 Extends Scope
Function lambda:Scope(env:Scope)
Return (New FibL2)._init(env)
End Function
 
Method apply:Object(args:Object[])
Local x:Int = Integer(args[0]).val
If x < 2
Return Integer.Make(x)
Else
Local f:Func = FibL1(env).f
Local x1:Int = Integer(f.apply([Integer.Make(x - 1)])).val
Local x2:Int = Integer(f.apply([Integer.Make(x - 2)])).val
Return Integer.Make(x1 + x2)
EndIf
End Method
End Type
 
 
'Now test
Local _Y:Func = Y.lambda(Null)
 
Local fac:Func = Func(_Y.apply([FacL1.lambda(Null)]))
Print Integer(fac.apply([Integer.Make(10)])).val
 
Local fib:Func = Func(_Y.apply([FibL1.lambda(Null)]))
Print Integer(fib.apply([Integer.Make(10)])).val

[edit] Bracmat

The lambda abstraction

 (λx.x)y

translates to

 /('(x.$x))$y

in Bracmat code. Likewise, the fixed point combinator

Y := λg.(λx.g (x x)) (λx.g (x x))

the factorial

G := λr. λn.(1, if n = 0; else n × (r (n−1)))

the Fibonacci function

H := λr. λn.(1, if n = 1 or n = 2; else (r (n−1)) + (r (n−2)))

and the calls

(Y G) i

and

(Y H) i

where i varies between 1 and 10, are translated into Bracmat as shown below

(   ( Y
= /(
' ( g
. /('(x.$g'($x'$x)))
$ /('(x.$g'($x'$x)))
)
)
)
& ( G
= /(
' ( r
. /(
' ( n
. $n:~>0&1
| $n*($r)$($n+-1)
)
)
)
)
)
& ( H
= /(
' ( r
. /(
' ( n
. $n:(1|2)&1
| ($r)$($n+-1)+($r)$($n+-2)
)
)
)
)
)
& 0:?i
& whl
' ( 1+!i:~>10:?i
& out$(str$(!i "!=" (!Y$!G)$!i))
)
& 0:?i
& whl
' ( 1+!i:~>10:?i
& out$(str$("fib(" !i ")=" (!Y$!H)$!i))
)
&
)

Output:

1!=1
2!=2
3!=6
4!=24
5!=120
6!=720
7!=5040
8!=40320
9!=362880
10!=3628800
fib(1)=1
fib(2)=1
fib(3)=2
fib(4)=3
fib(5)=5
fib(6)=8
fib(7)=13
fib(8)=21
fib(9)=34
fib(10)=55

[edit] C

C doesn't have first class functions, so we demote everything to second class to match.
#include <stdio.h>
#include <stdlib.h>
 
/* func: our one and only data type; it holds either a pointer to
a function call, or an integer. Also carry a func pointer to
a potential parameter, to simulate closure */

typedef struct func_t *func;
typedef struct func_t {
func (*func) (func, func), _;
int num;
} func_t;
 
func new(func(*f)(func, func), func _) {
func x = malloc(sizeof(func_t));
x->func = f;
x->_ = _; /* closure, sort of */
x->num = 0;
return x;
}
 
func call(func f, func g) {
return f->func(f, g);
}
 
func Y(func(*f)(func, func)) {
func _(func x, func y) { return call(x->_, y); }
func_t __ = { _ };
 
func g = call(new(f, 0), &__);
g->_ = g;
return g;
}
 
func num(int n) {
func x = new(0, 0);
x->num = n;
return x;
}
 
func fac(func f, func _null) {
func _(func self, func n) {
int nn = n->num;
return nn > 1 ? num(nn * call(self->_, num(nn - 1))->num)
: num(1);
}
 
return new(_, f);
}
 
func fib(func f, func _null) {
func _(func self, func n) {
int nn = n->num;
return nn > 1
? num( call(self->_, num(nn - 1))->num +
call(self->_, num(nn - 2))->num )
: num(1);
}
 
return new(_, f);
}
 
void show(func n) { printf(" %d", n->num); }
 
int main() {
int i;
func f = Y(fac);
printf("fac: ");
for (i = 1; i < 10; i++)
show( call(f, num(i)) );
printf("\n");
 
f = Y(fib);
printf("fib: ");
for (i = 1; i < 10; i++)
show( call(f, num(i)) );
printf("\n");
 
return 0;
}
Output
fac:  1 2 6 24 120 720 5040 40320 362880
fib:  1 2 3 5 8 13 21 34 55

[edit] C#

using System;
 
class Program
{
delegate Func<int, int> Recursive(Recursive recursive);
 
static void Main()
{
Func<Func<Func<int, int>, Func<int, int>>, Func<int, int>> Y =
f => ((Recursive)(g => (f(x => g(g)(x)))))((Recursive)(g => f(x => g(g)(x))));
 
var fac = Y(f => x => x < 2 ? 1 : x * f(x - 1));
var fib = Y(f => x => x < 2 ? x : f(x - 1) + f(x - 2));
 
Console.WriteLine(fac(6));
Console.WriteLine(fib(6));
}
}

Output:

720
8

[edit] C++

Works with: C++11

Known to work with GCC 4.7.2. Compile with

g++ --std=c++11 ycomb.cc
#include <iostream>
#include <functional>
 
template <typename F>
struct RecursiveFunc {
std::function<F(RecursiveFunc)> o;
};
 
template <typename A, typename B>
std::function<B(A)> fix (std::function<std::function<B(A)>(std::function<B(A)>)> f) {
RecursiveFunc<std::function<B(A)>> r = {
std::function<std::function<B(A)>(RecursiveFunc<std::function<B(A)>>)>([f](RecursiveFunc<std::function<B(A)>> w) {
return f(std::function<B(A)>([w](A x) {
return w.o(w)(x);
}));
})
};
return r.o(r);
}
 
typedef std::function<int(int)> Func;
typedef std::function<Func(Func)> FuncFunc;
FuncFunc almost_fac = [](Func f) {
return Func([f](int n) {
if (n <= 1) return 1;
return n * f(n - 1);
});
};
 
FuncFunc almost_fib = [](Func f) {
return Func([f](int n) {
if (n <= 2) return 1;
return f(n - 1) + f(n - 2);
});
};
 
int main() {
auto fib = fix(almost_fib);
auto fac = fix(almost_fac);
std::cout << "fib(10) = " << fib(10) << std::endl;
std::cout << "fac(10) = " << fac(10) << std::endl;
return 0;
}

[edit] Clojure

(defn Y [f]
((fn [x] (x x))
(fn [x]
(f (fn [& args]
(apply (x x) args))))))
 
(def fac
(fn [f]
(fn [n]
(if (zero? n) 1 (* n (f (dec n)))))))
 
(def fib
(fn [f]
(fn [n]
(condp = n
0 0
1 1
(+ (f (dec n))
(f (dec (dec n))))))))

Sample output:

user> ((Y fac) 10)
3628800
user> ((Y fib) 10)
55

Y can be written slightly more concisely via syntax sugar:

(defn Y [f]
(#(% %) #(f (fn [& args] (apply (% %) args)))))

[edit] Common Lisp

(defun Y (f)
((lambda (x) (funcall x x))
(lambda (y)
(funcall f (lambda (&rest args)
(apply (funcall y y) args))))))
 
(defun fac (f)
(lambda (n)
(if (zerop n)
1
(* n (funcall f (1- n))))))
 
(defun fib (f)
(lambda (n)
(case n
(0 0)
(1 1)
(otherwise (+ (funcall f (- n 1))
(funcall f (- n 2)))))))
 
? ((mapcar (y #'fac) '(1 2 3 4 5 6 7 8 9 10))
(1 2 6 24 120 720 5040 40320 362880 3628800))
 
? (mapcar (y #'fib) '(1 2 3 4 5 6 7 8 9 10))
(1 1 2 3 5 8 13 21 34 55)
 
 

[edit] CoffeeScript

Y = (f) -> g = f( (t...) -> g(t...) )

or

Y = (f) -> ((h)->h(h))((h)->f((t...)->h(h)(t...)))
fac = Y( (f) -> (n) -> if n > 1 then n * f(n-1) else 1 )
fib = Y( (f) -> (n) -> if n > 1 then f(n-1) + f(n-2) else n )
 

[edit] D

A stateless generic Y combinator:

import std.stdio, std.traits, std.algorithm, std.range;
 
auto Y(S, T...)(S delegate(T) delegate(S delegate(T)) f) {
static struct F {
S delegate(T) delegate(F) f;
alias f this;
}
return (x => x(x))(F(x => f((T v) => x(x)(v))));
}
 
void main() { // Demo code:
auto factorial = Y((int delegate(int) self) =>
(int n) => 0 == n ? 1 : n * self(n - 1)
);
 
auto ackermann = Y((ulong delegate(ulong, ulong) self) =>
(ulong m, ulong n) {
if (m == 0) return n + 1;
if (n == 0) return self(m - 1, 1);
return self(m - 1, self(m, n - 1));
});
 
writeln("factorial: ", 10.iota.map!factorial);
writeln("ackermann(3, 5): ", ackermann(3, 5));
}
Output:
factorial: [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
ackermann(3, 5): 253

[edit] Déjà Vu

Translation of: Python
Y f:
labda y:
labda:
call y @y
f
labda x:
x @x
call
 
labda f:
labda n:
if < 1 n:
* n f -- n
else:
1
set :fac Y
 
labda f:
labda n:
if < 1 n:
+ f - n 2 f -- n
else:
1
set :fib Y
 
!. fac 6
!. fib 6
Output:
720
13

[edit] Delphi

May work with Delphi 2009 and 2010 too.

Translation of: C++

(The translation is not literal; e.g. the function argument type is left unspecified to increase generality.)

program Y;
 
{$APPTYPE CONSOLE}
 
uses
SysUtils;
 
type
YCombinator = class sealed
class function Fix<T> (F: TFunc<TFunc<T, T>, TFunc<T, T>>): TFunc<T, T>; static;
end;
 
TRecursiveFuncWrapper<T> = record // workaround required because of QC #101272 (http://qc.embarcadero.com/wc/qcmain.aspx?d=101272)
type
TRecursiveFunc = reference to function (R: TRecursiveFuncWrapper<T>): TFunc<T, T>;
var
O: TRecursiveFunc;
end;
 
class function YCombinator.Fix<T> (F: TFunc<TFunc<T, T>, TFunc<T, T>>): TFunc<T, T>;
var
R: TRecursiveFuncWrapper<T>;
begin
R.O := function (W: TRecursiveFuncWrapper<T>): TFunc<T, T>
begin
Result := F (function (I: T): T
begin
Result := W.O (W) (I);
end);
end;
Result := R.O (R);
end;
 
 
type
IntFunc = TFunc<Integer, Integer>;
 
function AlmostFac (F: IntFunc): IntFunc;
begin
Result := function (N: Integer): Integer
begin
if N <= 1 then
Result := 1
else
Result := N * F (N - 1);
end;
end;
 
function AlmostFib (F: TFunc<Integer, Integer>): TFunc<Integer, Integer>;
begin
Result := function (N: Integer): Integer
begin
if N <= 2 then
Result := 1
else
Result := F (N - 1) + F (N - 2);
end;
end;
 
var
Fib, Fac: IntFunc;
begin
Fib := YCombinator.Fix<Integer> (AlmostFib);
Fac := YCombinator.Fix<Integer> (AlmostFac);
Writeln ('Fib(10) = ', Fib (10));
Writeln ('Fac(10) = ', Fac (10));
end.

[edit] E

Translation of: Python
def y := fn f { fn x { x(x) }(fn y { f(fn a { y(y)(a) }) }) }
def fac := fn f { fn n { if (n<2) {1} else { n*f(n-1) } }}
def fib := fn f { fn n { if (n == 0) {0} else if (n == 1) {1} else { f(n-1) + f(n-2) } }}
? pragma.enable("accumulator")
? accum [] for i in 0..!10 { _.with(y(fac)(i)) }
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
 
? accum [] for i in 0..!10 { _.with(y(fib)(i)) }
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

[edit] Eero

Translated from Objective-C example on this page.

#import <Foundation/Foundation.h>
 
typedef int (^Func)(int)
typedef Func (^FuncFunc)(Func)
typedef Func (^RecursiveFunc)(id) // hide recursive typing behind dynamic typing
 
Func fix(FuncFunc f)
Func r(RecursiveFunc g)
int s(int x)
return g(g)(x)
return f(s)
return r(r)
 
int main(int argc, const char *argv[])
autoreleasepool
 
Func almost_fac(Func f)
return (int n | return n <= 1 ? 1 : n * f(n - 1))
 
Func almost_fib(Func f)
return (int n | return n <= 2 ? 1 : f(n - 1) + f(n - 2))
 
fib := fix(almost_fib)
fac := fix(almost_fac)
 
Log('fib(10) = %d', fib(10))
Log('fac(10) = %d', fac(10))
 
return 0

[edit] Ela

fix = \f -> (\x -> & f (x x)) (\x -> & f (x x))
 
fac _ 0 = 1
fac f n = n * f (n - 1)
 
fib _ 0 = 0
fib _ 1 = 1
fib f n = f (n - 1) + f (n - 2)
 
(fix fac 12, fix fib 12)

Output:

(479001600,144)

[edit] Erlang

Y = fun(M) -> (fun(X) -> X(X) end)(fun (F) -> M(fun(A) -> (F(F))(A) end) end) end.
 
Fac = fun (F) ->
fun (0) -> 1;
(N) -> N * F(N-1)
end
end.
Fib = fun(F) ->
fun(0) -> 0;
(1) -> 1;
(N) -> F(N-1) + F(N-2)
end
end.
(Y(Fac))(5). %% 120
(Y(Fib))(8). %% 21

[edit] F#

type 'a mu = Roll of ('a mu -> 'a)  // ease syntax colouring confusion with '
 
let unroll (Roll x) = x
//val unroll : 'a mu -> 'a
 
let fix f = (fun x a -> f (unroll x x) a) (Roll (fun x a -> f (unroll x x) a))
//val fix : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b = <fun>
 
let fac f = function
0 -> 1
| n -> n * f (n-1)
//val fac : (int -> int) -> int -> int = <fun>
 
let fib f = function
0 -> 0
| 1 -> 1
| n -> f (n-1) + f (n-2)
//val fib : (int -> int) -> int -> int = <fun>
 
fix fac 5;;
// val it : int = 120
 
fix fib 8;;
// val it : int = 21

[edit] Factor

In rosettacode/Y.factor

USING: fry kernel math ;
IN: rosettacode.Y
: Y ( quot -- quot )
'[ [ dup call call ] curry @ ] dup call ; inline
 
: almost-fac ( quot -- quot )
'[ dup zero? [ drop 1 ] [ dup 1 - @ * ] if ] ;
 
: almost-fib ( quot -- quot )
'[ dup 2 >= [ 1 2 [ - @ ] bi-curry@ bi + ] when ] ;

In rosettacode/Y-tests.factor

USING: kernel tools.test rosettacode.Y ;
IN: rosettacode.Y.tests
 
[ 120 ] [ 5 [ almost-fac ] Y call ] unit-test
[ 8 ] [ 6 [ almost-fib ] Y call ] unit-test

running the tests :

 ( scratchpad - auto ) "rosettacode.Y" test
Loading resource:work/rosettacode/Y/Y-tests.factor
Unit Test: { [ 120 ] [ 5 [ almost-fac ] Y call ] }
Unit Test: { [ 8 ]   [ 6 [ almost-fib ] Y call ] }

[edit] Falcon

 
Y = { f => {x=> {n => f(x(x))(n)}} ({x=> {n => f(x(x))(n)}}) }
facStep = { f => {x => x < 1 ? 1 : x*f(x-1) }}
fibStep = { f => {x => x == 0 ? 0 : (x == 1 ? 1 : f(x-1) + f(x-2))}}
 
YFac = Y(facStep)
YFib = Y(fibStep)
 
> "Factorial 10: ", YFac(10)
> "Fibonacci 10: ", YFib(10)
 

[edit] GAP

Y := function(f)
local u;
u := x -> x(x);
return u(y -> f(a -> y(y)(a)));
end;
 
fib := function(f)
local u;
u := function(n)
if n < 2 then
return n;
else
return f(n-1) + f(n-2);
fi;
end;
return u;
end;
 
Y(fib)(10);
# 55
 
fac := function(f)
local u;
u := function(n)
if n < 2 then
return 1;
else
return n*f(n-1);
fi;
end;
return u;
end;
 
Y(fac)(8);
# 40320

[edit] Genyris

Translation of: Scheme
def fac (f)
function (n)
if (equal? n 0) 1
* n (f (- n 1))
def fib (f)
function (n)
cond
(equal? n 0) 0
(equal? n 1) 1
else (+ (f (- n 1)) (f (- n 2)))
 
def Y (f)
(function (x) (x x))
function (y)
f
function (&rest args) (apply (y y) args)
 
assertEqual ((Y fac) 5) 120
assertEqual ((Y fib) 8) 21

[edit] Go

package main
 
import "fmt"
 
type Func func(int) int
type FuncFunc func(Func) Func
type RecursiveFunc func (RecursiveFunc) Func
 
func main() {
fac := fix(almost_fac)
fib := fix(almost_fib)
fmt.Println("fac(10) = ", fac(10))
fmt.Println("fib(10) = ", fib(10))
}
 
func fix(f FuncFunc) Func {
g := func(r RecursiveFunc) Func {
return f(func(x int) int {
return r(r)(x)
})
}
return g(g)
}
 
func almost_fac(f Func) Func {
return func(x int) int {
if x <= 1 {
return 1
}
return x * f(x-1)
}
}
 
func almost_fib(f Func) Func {
return func(x int) int {
if x <= 2 {
return 1
}
return f(x-1)+f(x-2)
}
}

[edit] Groovy

Here is the simplest (unary) form of applicative order Y:

def Y = { le -> ({ f -> f(f) })({ f -> le { x -> f(f)(x) } }) }
 
def factorial = Y { fac ->
{ n -> n <= 2 ? n : n * fac(n - 1) }
}
 
assert 2432902008176640000 == factorial(20G)
 
def fib = Y { fibStar ->
{ n -> n <= 1 ? n : fibStar(n - 1) + fibStar(n - 2) }
}
 
assert fib(10) == 55

This version was translated from the one in The Little Schemer by Friedman and Felleisen. The use of the variable name le is due to the fact that the authors derive Y from an ordinary recursive length function.

A variadic version of Y in Groovy looks like this:

def Y = { le -> ({ f -> f(f) })({ f -> le { Object[] args -> f(f)(*args) } }) }
 
def mul = Y { mulStar -> { a, b -> a ? b + mulStar(a - 1, b) : 0 } }
 
1.upto(10) {
assert mul(it, 10) == it * 10
}

[edit] Haskell

The obvious definition of the Y combinator in Haskell canot be used because it contains an infinite recursive type (a = a -> b). Defining a data type (Mu) allows this recursion to be broken.

newtype Mu a = Roll { unroll :: Mu a -> a }
 
fix :: (a -> a) -> a
fix = \f -> (\x -> f (unroll x x)) $ Roll (\x -> f (unroll x x))
 
fac :: Integer -> Integer
fac = fix $ \f n -> if (n <= 0) then 1 else n * f (n-1)
 
fibs :: [Integer]
fibs = fix $ \fbs -> 0 : 1 : fix zipP fbs (tail fbs)
where zipP f (x:xs) (y:ys) = x+y : f xs ys
 
main = do
print $ map fac [1 .. 20]
print $ take 20 fibs

The usual version using recursion, disallowed by the task:

fix :: (a -> a) -> a
fix f = f (fix f)
 
fac :: Integer -> Integer
fac' f n | n <= 0 = 1
| otherwise = n * f (n-1)
fac = fix fac'

 
-- a simple but wasteful exponential time definition:
fib :: Integer -> Integer
fib' f 0 = 0
fib'
f 1 = 1
fib' f n = f (n-1) + f (n-2)
fib = fix fib'

 
-- Or for far more efficiency, compute a lazy infinite list. This is
-- a Y-combinator version of: fibs = 0:1:zipWith (+) fibs (tail fibs)
fibs :: [Integer]
fibs' a = 0:1:(fix zipP a (tail a))
where
zipP f (x:xs) (y:ys) = x+y : f xs ys
fibs = fix fibs'

 
-- This code shows how the functions can be used:
main = do
print $ map fac [1 .. 20]
print $ map fib [0 .. 19]
print $ take 20 fibs

[edit] J

In J, functions cannot take functions of the same type as arguments. In other words, verbs cannot take verbs and adverbs or conjunctions cannot take adverbs or conjunctions. However, the Y combinator can be implemented indirectly using, for example, the linear representations of verbs. (Y becomes a wrapper which takes a verb as an argument and serializes it, and the underlying self referring system interprets the serialized representation of a verb as the corresponding verb):

Y=. ((((&>)/)(1 : '(5!:5)<''x'''))(&([ 128!:2 ,&<)))f.

The factorial and Fibonacci examples:

   u=. [ NB. Function (left)
n=. ] NB. Argument (right)
sr=. [ 128!:2 ,&< NB. Self referring
 
fac=. (1:`(n * u sr n - 1:)) @. (0: < n)
fac f. Y 10
3628800
 
Fib=. ((u sr n - 2:) + u sr n - 1:) ^: (1: < n)
Fib f. Y 10
55

The functions' stateless codings are shown next:

   fac f. Y NB. Showing the stateless recursive factorial function...
'1:`(] * [ ([ 128!:2 ,&<) ] - 1:)@.(0: < ])&>/'&([ 128!:2 ,&<)
fac f. NB. Showing the stateless factorial step...
1:`(] * [ ([ 128!:2 ,&<) ] - 1:)@.(0: < ])
 
Fib f. Y NB. Showing the stateless recursive Fibonacci function...
'(([ ([ 128!:2 ,&<) ] - 2:) + [ ([ 128!:2 ,&<) ] - 1:)^:(1: < ])&>/'&([ 128!:2 ,&<)
Fib f. NB. Showing the stateless Fibonacci step...
(([ ([ 128!:2 ,&<) ] - 2:) + [ ([ 128!:2 ,&<) ] - 1:)^:(1: < ])

A structured derivation of Y follows:

sr=. [ 128!:2 ,&< NB. Self referring
lw=. '(5!:5)<''x''' (1 :) NB. Linear representation of a word
Y=. (&>)/lw(&sr) f.
Y=. 'Y'f. NB. Fixing it

[edit] alternate implementation

Another approach uses a J gerund as a "lambda" which can accept a single argument, and `:6 to mark a value which would correspond to the first element of an evaluated list in a lisp-like language.

(Multiple argument lambdas are handled by generating and evaluating an appropriate sequence of these lambdas -- in other words, (lambda (x y z) ...) is implemented as (lambda (x) (lambda (y) (lambda (z) ...))) and that particular example would be used as (((example X) Y) Z)) -- or, using J's syntax, that particular example would be used as: ((example`:6 X)`:6 Y)`:6 Z -- but we can also define a word with the value `:6 for a hypothetical slight increase in clarity.

lambda=:3 :0
if. 1=#;:y do.
3 :(y,'=.y',LF,0 :0)`''
else.
(,<#;:y) Defer (3 :('''',y,'''=.y',LF,0 :0))`''
end.
)
 
Defer=:2 :0
if. (_1 {:: m) <: #m do.
v |. y;_1 }. m
else.
(y;m) Defer v`''
end.
)
 
recursivelY=: lambda 'g recur x'
(g`:6 recur`:6 recur)`:6 x
)
 
sivelY=: lambda 'g recur'
(recursivelY`:6 g)`:6 recur
)
 
Y=: lambda 'g'
recur=. sivelY`:6 g
recur`:6 recur
)
 
almost_factorial=: lambda 'f n'
if. 0 >: n do. 1
else. n * f`:6 n-1 end.
)
 
almost_fibonacci=: lambda 'f n'
if. 2 > n do. n
else. (f`:6 n-1) + f`:6 n-2 end.
)
 
Ev=: `:6

Example use:

   (Y Ev almost_factorial)Ev 9
362880
(Y Ev almost_fibonacci)Ev 9
34
(Y Ev almost_fibonacci)Ev"0 i. 10
0 1 1 2 3 5 8 13 21 34

Note that the names f and recur will experience the same value (which will be the value produced by sivelY g).

[edit] Java

Java doesn't (currently) have function types. But we can use a generic function interface in the same way.

interface Function<A, B> {
public B call(A x);
}
 
public class YCombinator {
interface RecursiveFunc<F> extends Function<RecursiveFunc<F>, F> { }
 
public static <A,B> Function<A,B> fix(final Function<Function<A,B>, Function<A,B>> f) {
RecursiveFunc<Function<A,B>> r =
new RecursiveFunc<Function<A,B>>() {
public Function<A,B> call(final RecursiveFunc<Function<A,B>> w) {
return f.call(new Function<A,B>() {
public B call(A x) {
return w.call(w).call(x);
}
});
}
};
return r.call(r);
}
 
public static void main(String[] args) {
Function<Function<Integer,Integer>, Function<Integer,Integer>> almost_fib =
new Function<Function<Integer,Integer>, Function<Integer,Integer>>() {
public Function<Integer,Integer> call(final Function<Integer,Integer> f) {
return new Function<Integer,Integer>() {
public Integer call(Integer n) {
if (n <= 2) return 1;
return f.call(n - 1) + f.call(n - 2);
}
};
}
};
 
Function<Function<Integer,Integer>, Function<Integer,Integer>> almost_fac =
new Function<Function<Integer,Integer>, Function<Integer,Integer>>() {
public Function<Integer,Integer> call(final Function<Integer,Integer> f) {
return new Function<Integer,Integer>() {
public Integer call(Integer n) {
if (n <= 1) return 1;
return n * f.call(n - 1);
}
};
}
};
 
Function<Integer,Integer> fib = fix(almost_fib);
Function<Integer,Integer> fac = fix(almost_fac);
 
System.out.println("fib(10) = " + fib.call(10));
System.out.println("fac(10) = " + fac.call(10));
}
}
Works with: Java version 8+
import java.util.function.Function;
 
public class YCombinator {
interface RecursiveFunc<F> extends Function<RecursiveFunc<F>, F> { }
public static <A,B> Function<A,B> fix(Function<Function<A,B>, Function<A,B>> f) {
RecursiveFunc<Function<A,B>> r = w -> f.apply(x -> w.apply(w).apply(x));
return r.apply(r);
}
 
public static void main(String[] args) {
Function<Integer,Integer> fib = fix(f -> n -> {
if (n <= 2) return 1;
return f.apply(n - 1) + f.apply(n - 2);
});
Function<Integer,Integer> fac = fix(f -> n -> {
if (n <= 1) return 1;
return n * f.apply(n - 1);
});
 
System.out.println("fib(10) = " + fib.apply(10));
System.out.println("fac(10) = " + fac.apply(10));
}
}

The following code modifies the Function interface such that multiple parameters (via varargs) are supported, simplifies the y function considerably, and the Ackermann function has been included in this implementation (mostly because both D and PicoLisp include it in their own implementations).

import java.util.function.Function;
 
@FunctionalInterface
public interface SelfApplicable<OUTPUT> extends Function<SelfApplicable<OUTPUT>, OUTPUT> {
public default OUTPUT selfApply() {
return apply(this);
}
}
import java.util.function.Function;
import java.util.function.UnaryOperator;
 
@FunctionalInterface
public interface FixedPoint<FUNCTION> extends Function<UnaryOperator<FUNCTION>, FUNCTION> {}
import java.util.Arrays;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.BiFunction;
 
@FunctionalInterface
public interface VarargsFunction<INPUTS, OUTPUT> extends Function<INPUTS[], OUTPUT> {
@SuppressWarnings("unchecked")
public OUTPUT apply(INPUTS... inputs);
 
public static <INPUTS, OUTPUT> VarargsFunction<INPUTS, OUTPUT> from(Function<INPUTS[], OUTPUT> function) {
return function::apply;
}
 
public static <INPUTS, OUTPUT> VarargsFunction<INPUTS, OUTPUT> upgrade(Function<INPUTS, OUTPUT> function) {
return inputs -> function.apply(inputs[0]);
}
 
public static <INPUTS, OUTPUT> VarargsFunction<INPUTS, OUTPUT> upgrade(BiFunction<INPUTS, INPUTS, OUTPUT> function) {
return inputs -> function.apply(inputs[0], inputs[1]);
}
 
@SuppressWarnings("unchecked")
public default <POST_OUTPUT> VarargsFunction<INPUTS, POST_OUTPUT> andThen(
VarargsFunction<OUTPUT, POST_OUTPUT> after) {
return inputs -> after.apply(apply(inputs));
}
 
@SuppressWarnings("unchecked")
public default Function<INPUTS, OUTPUT> toFunction() {
return input -> apply(input);
}
 
@SuppressWarnings("unchecked")
public default BiFunction<INPUTS, INPUTS, OUTPUT> toBiFunction() {
return (input, input2) -> apply(input, input2);
}
 
@SuppressWarnings("unchecked")
public default <PRE_INPUTS> VarargsFunction<PRE_INPUTS, OUTPUT> transformArguments(Function<PRE_INPUTS, INPUTS> transformer) {
return inputs -> apply((INPUTS[]) Arrays.stream(inputs).parallel().map(transformer).toArray());
}
}
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
 
@FunctionalInterface
public interface Y<FUNCTION> extends SelfApplicable<FixedPoint<FUNCTION>> {
public static void main(String... arguments) {
BigInteger TWO = BigInteger.ONE.add(BigInteger.ONE);
 
Function<Number, Long> toLong = Number::longValue;
Function<Number, BigInteger> toBigInteger = toLong.andThen(BigInteger::valueOf);
 
/* Based on https://gist.github.com/aruld/3965968/#comment-604392 */
Y<VarargsFunction<Number, Number>> combinator = y -> f -> x -> f.apply(y.selfApply().apply(f)).apply(x);
FixedPoint<VarargsFunction<Number, Number>> fixedPoint = combinator.selfApply();
 
VarargsFunction<Number, Number> fibonacci = fixedPoint.apply(
f -> VarargsFunction.upgrade(
toBigInteger.andThen(
n -> (n.compareTo(TWO) <= 0)
? 1
 : new BigInteger(f.apply(n.subtract(BigInteger.ONE)).toString())
.add(new BigInteger(f.apply(n.subtract(TWO)).toString()))
)
)
);
 
VarargsFunction<Number, Number> factorial = fixedPoint.apply(
f -> VarargsFunction.upgrade(
toBigInteger.andThen(
n -> (n.compareTo(BigInteger.ONE) <= 0)
? 1
 : n.multiply(new BigInteger(f.apply(n.subtract(BigInteger.ONE)).toString()))
)
)
);
 
VarargsFunction<Number, Number> ackermann = fixedPoint.apply(
f -> VarargsFunction.upgrade(
(BigInteger m, BigInteger n) -> m.equals(BigInteger.ZERO)
? n.add(BigInteger.ONE)
 : f.apply(
m.subtract(BigInteger.ONE),
n.equals(BigInteger.ZERO)
? BigInteger.ONE
 : f.apply(m, n.subtract(BigInteger.ONE))
)
).transformArguments(toBigInteger)
);
 
Map<String, VarargsFunction<Number, Number>> functions = new HashMap<>();
functions.put("fibonacci", fibonacci);
functions.put("factorial", factorial);
functions.put("ackermann", ackermann);
 
Map<VarargsFunction<Number, Number>, Number[]> parameters = new HashMap<>();
parameters.put(functions.get("fibonacci"), new Number[]{20});
parameters.put(functions.get("factorial"), new Number[]{10});
parameters.put(functions.get("ackermann"), new Number[]{3, 2});
 
functions.entrySet().stream().parallel().map(
entry -> entry.getKey()
+ Arrays.toString(parameters.get(entry.getValue()))
+ " = "
+ entry.getValue().apply(parameters.get(entry.getValue()))
).forEach(System.out::println);
}
}

Output (may depend on which function gets processed first):

factorial[10] = 3628800
ackermann[3, 2] = 29
fibonacci[20] = 6765

[edit] JavaScript

function Y(f) {
var g = f(function() {
return g.apply(this, arguments);
});
return g;
}
 
var fac = Y(function(f) {
return function(n) {
return n > 1 ? n * f(n - 1) : 1;
};
});
 
var fib = Y(function(f) {
return function(n) {
return n > 1 ? f(n - 1) + f(n - 2) : n;
};
});

The standard version of the Y combinator does not use lexically bound local variables (or any local variables at all), which necessitates adding a wrapper function and some code duplication - the remaining locale variables are only there to make the relationship to the previous implementation more explicit:

function Y(f) {
var g = f((function(h) {
return function() {
var g = f(h(h));
return g.apply(this, arguments);
}
})(function(h) {
return function() {
var g = f(h(h));
return g.apply(this, arguments);
}
}));
return g;
}

Changing the oder of function application (ie the place where f gets called) and making use of the fact that we're generating a fixed-point, this can be reduced to

function Y(f) {
return (function(h) {
return h(h);
})(function(h) {
return f(function() {
return h(h).apply(this, arguments);
});
});
}

A functionally equivalent version using the implicit this parameter is also possible:

function pseudoY(f) {
return (function(h) {
return h(h);
})(function(h) {
return f.bind(function() {
return h(h).apply(null, arguments);
});
});
}
 
var fac = pseudoY(function(n) {
return n > 1 ? n * this(n - 1) : 1;
});
 
var fib = pseudoY(function(n) {
return n > 1 ? this(n - 1) + this(n - 2) : n;
});

However, pseudoY() is not a fixed-point combinator.

[edit] Joy

DEFINE y == [dup cons] swap concat dup cons i;
 
fac == [ [pop null] [pop succ] [[dup pred] dip i *] ifte ] y.

[edit] Lua

Y = function (f)
return function(...)
return (function(x) return x(x) end)(function(x) return f(function(y) return x(x)(y) end) end)(...)
end
end
 

Usage:

almostfactorial = function(f) return function(n) return n > 0 and n * f(n-1) or 1 end end
almostfibs = function(f) return function(n) return n < 2 and n or f(n-1) + f(n-2) end end
factorial, fibs = Y(almostfactorial), Y(almostfibs)
print(factorial(7))

[edit] Maple

 
> Y:=f->(x->x(x))(g->f((()->g(g)(args)))):
> Yfac:=Y(f->(x->`if`(x<2,1,x*f(x-1)))):
> seq( Yfac( i ), i = 1 .. 10 );
1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800
> Yfib:=Y(f->(x->`if`(x<2,x,f(x-1)+f(x-2)))):
> seq( Yfib( i ), i = 1 .. 10 );
1, 1, 2, 3, 5, 8, 13, 21, 34, 55
 

[edit] Mathematica

Y = Function[f, #@# &@Function[x, f[x[x]@# &]]];
factorial = Y@Function[f, If[# < 1, 1, # f[# - 1]] &];
fibonacci = Y@Function[f, If[# < 2, #, f[# - 1] + f[# - 2]] &];

[edit] Objective-C

Works with: Mac OS X version 10.6+
Works with: iOS version 4.0+
#import <Foundation/Foundation.h>
 
typedef int (^Func)(int);
typedef Func (^FuncFunc)(Func);
typedef Func (^RecursiveFunc)(id); // hide recursive typing behind dynamic typing
 
Func fix (FuncFunc f) {
RecursiveFunc r =
^(id y) {
RecursiveFunc w = y; // cast value back into desired type
return f(^(int x) {
return w(w)(x);
});
};
return r(r);
}
 
int main (int argc, const char *argv[]) {
@autoreleasepool {
 
FuncFunc almost_fac = ^Func(Func f) {
return ^(int n) {
if (n <= 1) return 1;
return n * f(n - 1);
};
};
 
FuncFunc almost_fib = ^Func(Func f) {
return ^(int n) {
if (n <= 2) return 1;
return f(n - 1) + f(n - 2);
};
};
 
Func fib = fix(almost_fib);
Func fac = fix(almost_fac);
NSLog(@"fib(10) = %d", fib(10));
NSLog(@"fac(10) = %d", fac(10));
 
}
return 0;
}

[edit] OCaml

The Y-combinator over functions may be written directly in OCaml provided rectypes are enabled:

let fix f g = (fun x a -> f (x x) a) (fun x a -> f (x x) a) g

Polymorphic variants are the simplest workaround in the absence of rectypes:

let fix f = (fun (`X x) -> f(x (`X x))) (`X(fun (`X x) y -> f(x (`X x)) y));;

Otherwise, an ordinary variant can be defined and used:

type 'a mu = Roll of ('a mu -> 'a);;
 
let unroll (Roll x) = x;;
 
let fix f = (fun x a -> f (unroll x x) a) (Roll (fun x a -> f (unroll x x) a));;
 
let fac f = function
0 -> 1
| n -> n * f (n-1)
;;
 
let fib f = function
0 -> 0
| 1 -> 1
| n -> f (n-1) + f (n-2)
;;
 
(* val unroll : 'a mu -> 'a mu -> 'a = <fun>
val fix : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b = <fun>
val fac : (int -> int) -> int -> int = <fun>
val fib : (int -> int) -> int -> int = <fun> *)

 
fix fac 5;;
(* - : int = 120 *)
 
fix fib 8;;
(* - : int = 21 *)

The usual version using recursion, disallowed by the task:

let rec fix f x = f (fix f) x;;

[edit] Order

#include <order/interpreter.h>
 
#define ORDER_PP_DEF_8y \
ORDER_PP_FN(8fn(8F, \
8let((8R, 8fn(8G, \
8ap(8F, 8fn(8A, 8ap(8ap(8G, 8G), 8A))))), \
8ap(8R, 8R))))

 
#define ORDER_PP_DEF_8fac \
ORDER_PP_FN(8fn(8F, 8X, \
8if(8less_eq(8X, 0), 1, 8times(8X, 8ap(8F, 8minus(8X, 1))))))

 
#define ORDER_PP_DEF_8fib \
ORDER_PP_FN(8fn(8F, 8X, \
8if(8less(8X, 2), 8X, 8plus(8ap(8F, 8minus(8X, 1)), \
8ap(8F, 8minus(8X, 2))))))

 
ORDER_PP(8to_lit(8ap(8y(8fac), 10))) // 3628800
ORDER_PP(8ap(8y(8fib), 10)) // 55

[edit] Oz

declare
Y = fun {$ F}
{fun {$ X} {X X} end
fun {$ X} {F fun {$ Z} {{X X} Z} end} end}
end
 
Fac = {Y fun {$ F}
fun {$ N}
if N == 0 then 1 else N*{F N-1} end
end
end}
 
Fib = {Y fun {$ F}
fun {$ N}
case N of 0 then 0
[] 1 then 1
else {F N-1} + {F N-2}
end
end
end}
in
{Show {Fac 5}}
{Show {Fib 8}}

[edit] Perl

sub Y { my $f = shift;                                # λf.
sub { my $x = shift; $x->($x) }->( # (λx.x x)
sub {my $y = shift; $f->(sub {$y->($y)(@_)})} # λy.f λz.y y z
)
}
my $fac = sub {my $f = shift;
sub {my $n = shift; $n < 2 ? 1 : $n * $f->($n-1)}
};
my $fib = sub {my $f = shift;
sub {my $n = shift; $n == 0 ? 0 : $n == 1 ? 1 : $f->($n-1) + $f->($n-2)}
};
for my $f ($fac, $fib) {
print join(' ', map Y($f)->($_), 0..9), "\n";
}
 
Output:
1 1 2 6 24 120 720 5040 40320 362880
0 1 1 2 3 5 8 13 21 34

[edit] Perl 6

sub Y ($f) { { .($_) }( -> $y { $f({ $y($y)($^arg) }) } ) }
sub fac ($f) { sub ($n) { $n < 2 ?? 1 !! $n * $f($n - 1) } }
sub fib ($f) { sub ($n) { $n < 2 ?? $n !! $f($n - 1) + $f($n - 2) } }
say map Y($_), ^10 for &fac, &fib;
Output:
1 1 2 6 24 120 720 5040 40320 362880
0 1 1 2 3 5 8 13 21 34

Note that Perl 6 doesn't actually need a Y combinator because you can name anonymous functions from the inside:

say .(10) given sub (Int $x) { $x < 2 ?? 1 !! $x * &?ROUTINE($x - 1); }

[edit] PHP

Works with: PHP version 5.3+
<?php
function Y($f) {
$g = function($w) use($f) {
return $f(function() use($w) {
return call_user_func_array($w($w), func_get_args());
});
};
return $g($g);
}
 
$fibonacci = Y(function($f) {
return function($i) use($f) { return ($i <= 1) ? $i : ($f($i-1) + $f($i-2)); };
});
 
echo $fibonacci(10), "\n";
 
$factorial = Y(function($f) {
return function($i) use($f) { return ($i <= 1) ? 1 : ($f($i - 1) * $i); };
});
 
echo $factorial(10), "\n";
?>


Works with: PHP version pre-5.3 and 5.3+

with create_function instead of real closures. A little far-fetched, but...

<?php
function Y($f) {
$g = create_function('$w', '$f = '.var_export($f,true).';
return $f(create_function(\'\', \'$w = \'.var_export($w,true).\';
return call_user_func_array($w($w), func_get_args());
\'));
'
);
return $g($g);
}
 
function almost_fib($f) {
return create_function('$i', '$f = '.var_export($f,true).';
return ($i <= 1) ? $i : ($f($i-1) + $f($i-2));
'
);
};
$fibonacci = Y('almost_fib');
echo $fibonacci(10), "\n";
 
function almost_fac($f) {
return create_function('$i', '$f = '.var_export($f,true).';
return ($i <= 1) ? 1 : ($f($i - 1) * $i);
'
);
};
$factorial = Y('almost_fac');
echo $factorial(10), "\n";
?>

A functionally equivalent version using the $this parameter in closures is also possible:

Works with: PHP version 5.4+
<?php
function pseudoY($f) {
$g = function($w) use ($f) {
return $f->bindTo(function() use ($w) {
return call_user_func_array($w($w), func_get_args());
});
};
return $g($g);
}
 
$factorial = pseudoY(function($n) {
return $n > 1 ? $n * $this($n - 1) : 1;
});
echo $factorial(10), "\n";
 
$fibonacci = pseudoY(function($n) {
return $n > 1 ? $this($n - 1) + $this($n - 2) : $n;
});
echo $fibonacci(10), "\n";
?>

However, pseudoY() is not a fixed-point combinator.

[edit] PicoLisp

Translation of: Common Lisp
(de Y (F)
(let X (curry (F) (Y) (F (curry (Y) @ (pass (Y Y)))))
(X X) ) )

[edit] Factorial

# Factorial
(de fact (F)
(curry (F) (N)
(if (=0 N)
1
(* N (F (dec N))) ) ) )
 
: ((Y fact) 6)
-> 720

[edit] Fibonacci sequence

# Fibonacci
(de fibo (F)
(curry (F) (N)
(if (> 2 N)
1
(+ (F (dec N)) (F (- N 2))) ) ) )
 
: ((Y fibo) 22)
-> 28657

[edit] Ackermann function

# Ackermann
(de ack (F)
(curry (F) (X Y)
(cond
((=0 X) (inc Y))
((=0 Y) (F (dec X) 1))
(T (F (dec X) (F X (dec Y)))) ) ) )
 
: ((Y ack) 3 4)
-> 125

[edit] Pop11

define Y(f);
procedure (x); x(x) endprocedure(
procedure (y);
f(procedure(z); (y(y))(z) endprocedure)
endprocedure
)
enddefine;
 
define fac(h);
procedure (n);
if n = 0 then 1 else n * h(n - 1) endif
endprocedure
enddefine;
 
define fib(h);
procedure (n);
if n < 2 then 1 else h(n - 1) + h(n - 2) endif
endprocedure
enddefine;
 
Y(fac)(5) =>
Y(fib)(5) =>

Output:

** 120
** 8

[edit] PostScript

Translation of: Joy
Library: initlib
y {
{dup cons} exch concat dup cons i
}.
 
/fac {
{ {pop zero?} {pop succ} {{dup pred} dip i *} ifte }
y
}.

[edit] PowerShell

Translation of: Python

PowerShell Doesn't have true closure, in order to fake it, the script-block is converted to text and inserted whole into the next function using variable expansion in double-quoted strings. For simple translation of lambda calculus, lambda translates as param inside of a ScriptBlock, (\ldots) translates as Invoke-Expression "{}", invocation (written as a space) translates to InvokeReturnAsIs. \begin{array}{lcl}
fac & := & \lambda f.(\lambda n.\mbox{if }n\leq0\mbox{ then }1\mbox{ else }n*(f\ n-1)) \\
fib & := & \lambda f.(\lambda n. \mbox{if }n=0\mbox{ or }n=1\mbox{ then }1\mbox{ else }(f\ n-1)+(f\ n-2)) \\
Z & := & \lambda f.(\lambda x.f\ (\lambda y.x\ x\ y))\ (\lambda x.f\ (\lambda y.x\ x\ y)) \\
\end{array}

$fac = {
param([ScriptBlock] $f)
invoke-expression @"
{
param([int] `$n)
if (`$n -le 0) {1}
else {`$n * {$f}.InvokeReturnAsIs(`$n - 1)}
}
"
@
}
 
$fib = {
param([ScriptBlock] $f)
invoke-expression @"
{
param([int] `$n)
switch (`$n)
{
0 {1}
1 {1}
default {{$f}.InvokeReturnAsIs(`$n-1)+{$f}.InvokeReturnAsIs(`$n-2)}
}
}
"
@
}
 
$Z = {
param([ScriptBlock] $f)
invoke-expression @"
{
param([ScriptBlock] `$x)
{$f}.InvokeReturnAsIs(`$(invoke-expression @`"
{
param(```$y)
{`$x}.InvokeReturnAsIs({`$x}).InvokeReturnAsIs(```$y)
}
`"@))
}.InvokeReturnAsIs({
param([ScriptBlock] `$x)
{$f}.InvokeReturnAsIs(`$(invoke-expression @`"
{
param(```$y)
{`$x}.InvokeReturnAsIs({`$x}).InvokeReturnAsIs(```$y)
}
`"@))
})
"
@
}
 
$Z.InvokeReturnAsIs($fac).InvokeReturnAsIs(5)
$Z.InvokeReturnAsIs($fib).InvokeReturnAsIs(5)

[edit] Prolog

Works with SWI-Prolog and module lambda, written by Ulrich Neumerkel found there http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl.

The code is inspired from this page : http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord#Hiord (p 106).
Original code is from Hermenegildo and al : Hiord: A Type-Free Higher-Order Logic Programming Language with Predicate Abstraction, pdf accessible here http://www.stups.uni-duesseldorf.de/asap/?id=129.

:- use_module(lambda).
 
% The Y combinator
y(P, Arg, R) :-
Pred = P +\Nb2^F2^call(P,Nb2,F2,P),
call(Pred, Arg, R).
 
 
test_y_combinator :-
% code for Fibonacci function
Fib = \NFib^RFib^RFibr1^(NFib < 2 ->
RFib = NFib
;
NFib1 is NFib - 1,
NFib2 is NFib - 2,
call(RFibr1,NFib1,RFib1,RFibr1),
call(RFibr1,NFib2,RFib2,RFibr1),
RFib is RFib1 + RFib2
),
 
y(Fib, 10, FR), format('Fib(~w) = ~w~n', [10, FR]),
 
% code for Factorial function
Fact = \NFact^RFact^RFactr1^(NFact = 1 ->
RFact = NFact
;
NFact1 is NFact - 1,
call(RFactr1,NFact1,RFact1,RFactr1),
RFact is NFact * RFact1
),
 
y(Fact, 10, FF), format('Fact(~w) = ~w~n', [10, FF]).

The output :

 ?- test_y_combinator.
Fib(10) = 55
Fact(10) = 3628800
true.

[edit] Python

>>> Y = lambda f: (lambda x: x(x))(lambda y: f(lambda *args: y(y)(*args)))
>>> fac = lambda f: lambda n: (1 if n<2 else n*f(n-1))
>>> [ Y(fac)(i) for i in range(10) ]
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
>>> fib = lambda f: lambda n: 0 if n == 0 else (1 if n == 1 else f(n-1) + f(n-2))
>>> [ Y(fib)(i) for i in range(10) ]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

[edit] R

Y <- function(f) {
(function(x) { (x)(x) })( function(y) { f( (function(a) {y(y)})(a) ) } )
}
fac <- function(f) {
function(n) {
if (n<2)
1
else
n*f(n-1)
}
}
 
fib <- function(f) {
function(n) {
if (n <= 1)
n
else
f(n-1) + f(n-2)
}
}
for(i in 1:9) print(Y(fac)(i))
for(i in 1:9) print(Y(fib)(i))

[edit] Racket

The lazy implementation

 
#lang lazy
 
(define Y (λ(f)((λ(x)(f (x x)))(λ(x)(f (x x))))))
 
(define Fact
(Y (λ(fact) (λ(n) (if (zero? n) 1 (* n (fact (- n 1))))))))
(define Fib
(Y (λ(fib) (λ(n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))))))
 

Output:

> (!! (map Fact '(1 2 4 8 16)))
'(1 2 24 40320 20922789888000)
> (!! (map Fib '(1 2 4 8 16)))
'(0 1 2 13 610)

Strict realization:

 
#lang racket
(define Y (λ(b)((λ(f)(b(λ(x)((f f) x))))
(λ(f)(b(λ(x)((f f) x)))))))
 

Definitions of Fact and Fib functions will be the same as in Lazy Racket.

Finally, a definition in Typed Racket is a little difficult as in other statically typed languages:

 
#lang typed/racket
 
(: make-recursive : (All (S T) ((S -> T) -> (S -> T)) -> (S -> T)))
(define-type Tau (All (S T) (Rec this (this -> (S -> T)))))
(define (make-recursive f)
((lambda: ([x : (Tau S T)]) (f (lambda (z) ((x x) z))))
(lambda: ([x : (Tau S T)]) (f (lambda (z) ((x x) z))))))
 
(: fact : Number -> Number)
(define fact (make-recursive
(lambda: ([fact : (Number -> Number)])
(lambda: ([n : Number])
(if (zero? n)
1
(* n (fact (- n 1))))))))
 
(fact 5)
 

[edit] REBOL

Y: closure [g] [do func [f] [f :f] closure [f] [g func [x] [do f :f :x]]]
usage example
fact*: closure [h] [func [n] [either n <= 1 [1] [n * h n - 1]]]
fact: Y :fact*

[edit] REXX

/*REXX program to implement a  stateless  Y  combinator. */
numeric digits 1000 /*allow big 'uns. */
 
say ' fib' Y(fib (50)) /*Fibonacci series*/
say ' fib' Y(fib (12 11 10 9 8 7 6 5 4 3 2 1 0)) /*Fibonacci series*/
say ' fact' Y(fact (60)) /*single fact. */
say ' fact' Y(fact (0 1 2 3 4 5 6 7 8 9 10 11)) /*single fact. */
say ' Dfact' Y(dfact (4 5 6 7 8 9 10 11 12 13)) /*double fact. */
say ' Tfact' Y(tfact (4 5 6 7 8 9 10 11 12 13)) /*triple fact. */
say ' Qfact' Y(qfact (4 5 6 7 8 40)) /*quadruple fact. */
say ' length' Y(length (when for to where whenceforth)) /*lengths of words*/
say 'reverse' Y(reverse (23 678 1007 45 MAS I MA)) /*reverses strings*/
say ' trunc' Y(trunc (-7.0005 12 3.14159 6.4 78.999)) /*truncates numbs.*/
exit /*stick a fork in it, we're done.*/
 
/*──────────────────────────────────subroutines─────────────────────────*/
Y: lambda=; parse arg Y _; do j=1 for words(_); interpret ,
'lambda=lambda' Y'('word(_,j)')'; end; return lambda
fib: procedure; parse arg x; if x<2 then return x; s=0; a=0; b=1
do j=2 to x; s=a+b; a=b; b=s; end; return s
dfact: procedure; arg x; !=1; do j=x to 2 by -2;!=!*j; end; return !
tfact: procedure; arg x; !=1; do j=x to 2 by -3;!=!*j; end; return !
qfact: procedure; arg x; !=1; do j=x to 2 by -4;!=!*j; end; return !
fact: procedure; arg x; !=1; do j=2 to x  ;!=!*j; end; return !

output

    fib  12586269025
    fib  144 89 55 34 21 13 8 5 3 2 1 1 0
   fact  8320987112741390144276341183223364380754172606361245952449277696409600000000000000
   fact  1 1 2 6 24 120 720 5040 40320 362880 3628800 39916800
  Dfact  8 15 48 105 384 945 3840 10395 46080 135135
  Tfact  4 10 18 28 80 162 280 880 1944 3640
  Qfact  4 5 12 21 32 3805072588800
 length  4 3 2 5 11
reverse  32 876 7001 54 SAM I AM
  trunc  -7 12 3 6 78

[edit] Ruby

Using a lambda:

y = lambda do |f|
lambda {|g| g[g]}[lambda do |g|
f[lambda {|*args| g[g][*args]}]
end]
end
 
fac = lambda{|f| lambda{|n| n < 2 ? 1 : n * f[n-1]}}
p Array.new(10) {|i| y[fac][i]} #=> [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
 
fib = lambda{|f| lambda{|n| n < 2 ? n : f[n-1] + f[n-2]}}
p Array.new(10) {|i| y[fib][i]} #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Using a method:

Works with: Ruby version 1.9
def y(&f)
lambda do |g|
f.call {|*args| g[g][*args]}
end.tap {|g| break g[g]}
end
 
fac = y {|&f| lambda {|n| n < 2 ? 1 : n * f[n - 1]}}
fib = y {|&f| lambda {|n| n < 2 ? n : f[n - 1] + f[n - 2]}}
 
p Array.new(10) {|i| fac[i]}
# => [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
p Array.new(10) {|i| fib[i]}
# => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

[edit] Rust

Works with: Rust version 0.7
enum Mu<T> { Roll(@fn(Mu<T>) -> T) }
fn unroll<T>(Roll(f): Mu<T>) -> @fn(Mu<T>) -> T { f }
 
type RecFunc<A, B> = @fn(@fn(A) -> B) -> @fn(A) -> B;
 
fn fix<A, B>(f: RecFunc<A, B>) -> @fn(A) -> B {
let g: @fn(Mu<@fn(A) -> B>) -> @fn(A) -> B =
|x| |a| f(unroll(x)(x))(a);
g(Roll(g))
}
 
fn main() {
let fac: RecFunc<uint, uint> =
|f| |x| if (x==0) { 1 } else { f(x-1) * x };
let fib : RecFunc<uint, uint> =
|f| |x| if (x<2) { 1 } else { f(x-1) + f(x-2) };
 
let ns = std::vec::from_fn(20, |i| i);
println(fmt!("%?", ns.map(|&n| fix(fac)(n))));
println(fmt!("%?", ns.map(|&n| fix(fib)(n))));
}

Derived from: [1]

[edit] Scala

Credit goes to the thread in scala blog

def Y[A,B](f: (A=>B)=>(A=>B)) = {
case class W(wf: W=>A=>B) {
def apply(w: W) = wf(w)
}
val g: W=>A=>B = w => f(w(w))(_)
g(W(g))
}

Example

val fac = Y[Int, Int](f => i => if (i <= 0) 1 else f(i - 1) * i)
fac(6) //> res0: Int = 720
 
val fib = Y[Int, Int](f => i => if (i < 2) i else f(i - 1) + f(i - 2))
fib(6) //> res1: Int = 8

[edit] Scheme

(define Y
(lambda (f)
((lambda (x) (x x))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
 
(define fac
(Y
(lambda (f)
(lambda (x)
(if (< x 2)
1
(* x (f (- x 1))))))))
 
(define fib
(Y
(lambda (f)
(lambda (x)
(if (< x 2)
x
(+ (f (- x 1)) (f (- x 2))))))))
 
(display (fac 6))
(newline)
 
(display (fib 6))
(newline)

Output:

720
8

[edit] Slate

The Y combinator is already defined in slate as:

Method traits define: #Y &builder:
[[| :f | [| :x | f applyWith: (x applyWith: x)]
applyWith: [| :x | f applyWith: (x applyWith: x)]]].

[edit] Smalltalk

Works with: GNU Smalltalk
Y := [:f| [:x| x value: x] value: [:g| f value: [:x| (g value: g) value: x] ] ].
 
fib := Y value: [:f| [:i| i <= 1 ifTrue: [i] ifFalse: [(f value: i-1) + (f value: i-2)] ] ].
 
(fib value: 10) displayNl.
 
fact := Y value: [:f| [:i| i = 0 ifTrue: [1] ifFalse: [(f value: i-1) * i] ] ].
 
(fact value: 10) displayNl.

Output:

55
3628800

[edit] Standard ML

- datatype 'a mu = Roll of ('a mu -> 'a)
fun unroll (Roll x) = x
 
fun fix f = (fn x => fn a => f (unroll x x) a) (Roll (fn x => fn a => f (unroll x x) a))
 
fun fac f 0 = 1
| fac f n = n * f (n-1)
 
fun fib f 0 = 0
| fib f 1 = 1
| fib f n = f (n-1) + f (n-2)
;
datatype 'a mu = Roll of 'a mu -> 'a
val unroll = fn : 'a mu -> 'a mu -> 'a
val fix = fn : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b
val fac = fn : (int -> int) -> int -> int
val fib = fn : (int -> int) -> int -> int
- List.tabulate (10, fix fac);
val it = [1,1,2,6,24,120,720,5040,40320,362880] : int list
- List.tabulate (10, fix fib);
val it = [0,1,1,2,3,5,8,13,21,34] : int list

[edit] Tcl

Y combinator is derived in great detail here.

[edit] TXR

This prints out 24, the factorial of 4:

@(do 
 ;; The Y combinator:
(defun y (f)
[(op @1 @1)
(op f (op [@@1 @@1]))])
 
 ;; The Y-combinator-based factorial:
(defun fac (f)
(do if (zerop @1)
1
(* @1 [f (- @1 1)])))
 
 ;; Test:
(format t "~s\n" [[y fac] 4]))

Both the op and do operators are a syntactic sugar for currying, in two different flavors. The forms within do that are symbols are evaluated in the normal Lisp-2 style and the first symbol can be an operator. Under op, any forms that are symbols are evaluated in the Lisp-2 style, and the first form is expected to evaluate to a function. The name do stems from the fact that the operator is used for currying over special forms like if in the above example, where there is evaluation control. Operators can have side effects: they can "do" something. Consider (do set a @1) which yields a function of one argument which assigns that argument to a.

The compounded @@ is new in TXR 77. When the currying syntax is nested, code in an inner op/do can refer to numbered implicit parameters in an outer op/do. Each additional @ "escapes" out one nesting level.

[edit] Ursala

The standard y combinator doesn't work in Ursala due to eager evaluation, but an alternative is easily defined as shown

(r "f") "x" = "f"("f","x")
my_fix "h" = r ("f","x"). ("h" r "f") "x"

or by this shorter expression for the same thing in point free form.

my_fix = //~&R+ ^|H\~&+ ; //~&R

Normally you'd like to define a function recursively by writing f = h(f), where h(f) is just the body of the function with recursive calls to f in it. With a fixed point combinator such as my_fix as defined above, you do almost the same thing, except it's f = my_fix "f". h("f"), where the dot represents lambda abstraction and the quotes signify a dummy variable. Using this method, the definition of the factorial function becomes

#import nat
 
fact = my_fix "f". ~&?\1! product^/~& "f"+ predecessor

To make it easier, the compiler has a directive to let you install your own fixed point combinator for it to use, which looks like this,

#fix my_fix

with your choice of function to be used in place of my_fix. Having done that, you may express recursive functions per convention by circular definitions, as in this example of a Fibonacci function.

fib = {0,1}?</1! sum+ fib~~+ predecessor^~/~& predecessor

Note that this way is only syntactic sugar for the for explicit way shown above. Without a fixed point combinator given in the #fix directive, this definition of fib would not have compiled. (Ursala allows user defined fixed point combinators because they're good for other things besides functions.) To confirm that all this works, here is a test program applying both of the functions defined above to the numbers from 1 to 8.

#cast %nLW
 
examples = (fact* <1,2,3,4,5,6,7,8>,fib* <1,2,3,4,5,6,7,8>)

output:

(
   <1,2,6,24,120,720,5040,40320>,
   <1,2,3,5,8,13,21,34>)

The fixed point combinator defined above is theoretically correct but inefficient and limited to first order functions, whereas the standard distribution includes a library (sol) providing a hierarchy of fixed point combinators suitable for production use and with higher order functions. A more efficient alternative implementation of my_fix would be general_function_fixer 0 (with 0 signifying the lowest order of fixed point combinators), or if that's too easy, then by this definition.

#import sol
 
#fix general_function_fixer 1
 
my_fix "h" = "h" my_fix "h"

Note that this equation is solved using the next fixed point combinator in the hierarchy.

[edit] Wart

def (Y improver)
((fn(gen) gen.gen)
(fn(gen)
(fn(n)
((improver gen.gen) n))))
 
factorial <- (Y (fn(f)
(fn(n)
(if zero?.n
1
(n * (f n-1))))))
 
prn factorial.5

[edit] XQuery

Version 3.0 of the XPath and XQuery specifications added support for function items.

let $Y := function($f) {  
(function($x) { ($x)($x) })( function($g) { $f( (function($a) { $g($g) ($a)}) ) } )
}
let $fac := $Y(function($f) { function($n) { if($n < 2) then 1 else $n * $f($n - 1) } })
let $fib := $Y(function($f) { function($n) { if($n <= 1) then $n else $f($n - 1) + $f($n - 2) } })
return (
$fac(6),
$fib(6)
)
 

Output

720 8

[edit] zkl

fcn Y(f){ fcn(g){g(g)}( 'wrap(h){ f( 'wrap(a){ h(h)(a) } ) } )}

Functions don't get to look outside of their scope so data in enclosing scopes needs to be bound to a function, the fp method does this. 'wrap is syntactic sugar for fp.

fcn almost_factorial(f){ fcn(n,f){ if(n<=1) 1 else n*f(n-1) }.fp1(f) }
Y(almost_factorial)(6).println();
[0..10].apply(Y(almost_factorial)).println();
Output:
720
L(1,1,2,6,24,120,720,5040,40320,362880,3628800)
fcn almost_fib(f){ fcn(n,f){ if(n<2) 1 else f(n-1)+f(n-2) }.fp1(f) }
Y(almost_fib)(9).println();
[0..10].apply(Y(almost_fib)).println();
Output:
55
L(1,1,2,3,5,8,13,21,34,55,89)
Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox