# 各语言Y组合子大比拼

Y = lambda f. (lambda x. f(x , x)) , (lambda x. f(x , x))

## Python魔法

```Y = lambda f: (lambda x: f(x(x)))((lambda x: f(lambda *args: x(x)(*args))))
```

## JavaScript魔法

```Y = f => (x => f(x(x))) ((x => f(...a => x(x)(...a))))
```

## CoffeeScript黑魔法

```Y = (f) -> ((g) -> f (g g)) ((g) -> f (...x) -> (g g) ...x)
```

```import Unsafe.Coerce

y :: (a -> a) -> a
y = f -> (x -> f (unsafeCoerce x x)) (x -> f (unsafeCoerce x x))
```

）。

```newtype Mu a = Mu (Mu a -> a)
y f = (h -> h \$ Mu h) (x -> f . ((Mu g) -> g) x \$ x)
```

```y f = (x -> f . ((Mu g) -> g) x \$ x) \$ Mu (x -> f . ((Mu g) -> g) x \$ x)
```

```y f = f . ((Mu g) -> g) Mu (x -> f . ((Mu g) -> g) x \$ x) \$ Mu (x -> f . ((Mu g) -> g) x \$ x))
= f . (x -> f . ((Mu g) -> g) x \$ x) \$ Mu (x -> f . ((Mu g) -> g) x \$ x))
= f . y f
```

## Lisp（Scheme）

```(define (Y f) (lambda (f)
((lambda (x)
(f (lambda (arg) ((x x) arg))))
(lambda (x)
(f (lambda (arg) ((x x) arg)))))))
```

Scheme还是很纯粹很好看的。

Java作为一个有类型检查，lambda是语法糖的语言，想写Y组合子必然是痛苦的。我从 Gists

```package test;

import java.math.BigInteger;
import java.util.function.Function;

public class YCombinatorFactorial {
private interface Improver {
Function apply( Improver f ) ;
}

private Function Y( final Function<Function,Function> r ) {
return ((Improver)f -> f.apply( f )).apply( f -> r.apply( x -> f.apply( f ).apply( x ) ) ) ;
}

public static void main( String[] args ) {
YCombinatorFactorial yf = new YCombinatorFactorial() ;
BigInteger result = yf.Y(
f -> n -> n.equals( BigInteger.ZERO ) ?
BigInteger.ONE :
n.multiply( f.apply(n.subtract( BigInteger.ONE ) ) ) ).apply( BigInteger.valueOf( 100 ) ) ;
System.out.println( result );
}
}
```

```((Improver)f -> f.apply( f )).apply( f -> r.apply( x -> f.apply( f ).apply( x ) ) );
(f -> r.apply( x -> f.apply( f ).apply( x ) )).apply( f -> r.apply( x -> f.apply( f ).apply( x ) ) );
```

## WolframScript真魔法

```yCombinator@f_ := #@# &[Function[n, f[#@#]@n] &];
```