Y combinator: Difference between revisions
Content added Content deleted
m (→{{header|Joy}}) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 22: | Line 22: | ||
=={{header|AArch64 Assembly}}== |
=={{header|AArch64 Assembly}}== |
||
{{works with|as|Raspberry Pi 3B version Buster 64 bits}} |
{{works with|as|Raspberry Pi 3B version Buster 64 bits}} |
||
<syntaxhighlight lang="aarch64 assembly"> |
|||
<lang AArch64 Assembly> |
|||
/* ARM assembly AARCH64 Raspberry PI 3B */ |
/* ARM assembly AARCH64 Raspberry PI 3B */ |
||
/* program Ycombi64.s */ |
/* program Ycombi64.s */ |
||
Line 287: | Line 287: | ||
/* for this file see task include a file in language AArch64 assembly */ |
/* for this file see task include a file in language AArch64 assembly */ |
||
.include "../includeARM64.inc" |
.include "../includeARM64.inc" |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
Line 296: | Line 296: | ||
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - compile not currently available on my system.}} |
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - compile not currently available on my system.}} |
||
{{wont work with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny] - correctly detects a scope violation}} --> |
{{wont work with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny] - correctly detects a scope violation}} --> |
||
< |
<syntaxhighlight lang="algol68">BEGIN |
||
MODE F = PROC(INT)INT; |
MODE F = PROC(INT)INT; |
||
MODE Y = PROC(Y)F; |
MODE Y = PROC(Y)F; |
||
Line 306: | Line 306: | ||
FOR i TO 10 DO print(y(fib)(i)) OD |
FOR i TO 10 DO print(y(fib)(i)) OD |
||
END</ |
END</syntaxhighlight> |
||
<!-- |
<!-- |
||
ALGOL 68G Output demonstrating the runtime scope violation: |
ALGOL 68G Output demonstrating the runtime scope violation: |
||
Line 325: | Line 325: | ||
These could easily be fixed by changing names, but I believe that doing so would make the code harder to follow. |
These could easily be fixed by changing names, but I believe that doing so would make the code harder to follow. |
||
< |
<syntaxhighlight lang="algol68">BEGIN |
||
# This version needs partial parameterisation in order to work # |
# This version needs partial parameterisation in order to work # |
||
Line 401: | Line 401: | ||
print( newline ) |
print( newline ) |
||
END</ |
END</syntaxhighlight> |
||
=={{header|AppleScript}}== |
=={{header|AppleScript}}== |
||
Line 411: | Line 411: | ||
The identifier used for Y uses "pipe quoting" to make it obviously distinct from the y used inside the definition. |
The identifier used for Y uses "pipe quoting" to make it obviously distinct from the y used inside the definition. |
||
< |
<syntaxhighlight lang="applescript">-- Y COMBINATOR --------------------------------------------------------------- |
||
on |Y|(f) |
on |Y|(f) |
||
Line 507: | Line 507: | ||
end script |
end script |
||
end if |
end if |
||
end mReturn</ |
end mReturn</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
< |
<syntaxhighlight lang="applescript">{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}}</ |
fibs:{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765}}</syntaxhighlight> |
||
=={{header|ARM Assembly}}== |
=={{header|ARM Assembly}}== |
||
{{works with|as|Raspberry Pi}} |
{{works with|as|Raspberry Pi}} |
||
<syntaxhighlight lang="arm assembly"> |
|||
<lang ARM Assembly> |
|||
/* ARM assembly Raspberry PI */ |
/* ARM assembly Raspberry PI */ |
||
Line 767: | Line 767: | ||
.include "../affichage.inc" |
.include "../affichage.inc" |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{output}} |
{{output}} |
||
<pre> |
<pre> |
||
Line 797: | Line 797: | ||
=={{header|ATS}}== |
=={{header|ATS}}== |
||
<syntaxhighlight lang="ats"> |
|||
<lang ATS> |
|||
(* ****** ****** *) |
(* ****** ****** *) |
||
// |
// |
||
Line 822: | Line 822: | ||
// |
// |
||
(* ****** ****** *) |
(* ****** ****** *) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|BlitzMax}}== |
=={{header|BlitzMax}}== |
||
BlitzMax doesn't support anonymous functions or classes, so everything needs to be explicitly named. |
BlitzMax doesn't support anonymous functions or classes, so everything needs to be explicitly named. |
||
< |
<syntaxhighlight lang="blitzmax">SuperStrict |
||
'Boxed type so we can just use object arrays for argument lists |
'Boxed type so we can just use object arrays for argument lists |
||
Line 981: | Line 981: | ||
Local fib:Func = Func(_Y.apply([FibL1.lambda(Null)])) |
Local fib:Func = Func(_Y.apply([FibL1.lambda(Null)])) |
||
Print Integer(fib.apply([Integer.Make(10)])).val</ |
Print Integer(fib.apply([Integer.Make(10)])).val</syntaxhighlight> |
||
=={{header|Bracmat}}== |
=={{header|Bracmat}}== |
||
Line 999: | Line 999: | ||
<pre>(Y H) i</pre> |
<pre>(Y H) i</pre> |
||
where i varies between 1 and 10, are translated into Bracmat as shown below |
where i varies between 1 and 10, are translated into Bracmat as shown below |
||
< |
<syntaxhighlight lang="bracmat">( ( Y |
||
= /( |
= /( |
||
' ( g |
' ( g |
||
Line 1,042: | Line 1,042: | ||
) |
) |
||
& |
& |
||
)</ |
)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>1!=1 |
<pre>1!=1 |
||
Line 1,066: | Line 1,066: | ||
=={{header|C}}== |
=={{header|C}}== |
||
C doesn't have first class functions, so we demote everything to second class to match.< |
C doesn't have first class functions, so we demote everything to second class to match.<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Line 1,136: | Line 1,136: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 1,150: | Line 1,150: | ||
''Note: in the code, <code>Func<T, TResult></code> is a delegate type (the CLR equivalent of a function pointer) that has a parameter of type <code>T</code> and return type of <code>TResult</code>. See [[Higher-order functions#C#]] or [https://docs.microsoft.com/en-us/dotnet/standard/delegates-lambdas the documentation] for more information.'' |
''Note: in the code, <code>Func<T, TResult></code> is a delegate type (the CLR equivalent of a function pointer) that has a parameter of type <code>T</code> and return type of <code>TResult</code>. See [[Higher-order functions#C#]] or [https://docs.microsoft.com/en-us/dotnet/standard/delegates-lambdas the documentation] for more information.'' |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
static class YCombinator<T, TResult> |
static class YCombinator<T, TResult> |
||
Line 1,172: | Line 1,172: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre>3628800 |
<pre>3628800 |
||
Line 1,178: | Line 1,178: | ||
Alternatively, with a non-generic holder class (note that <code>Fix</code> is now a method, as properties cannot be generic): |
Alternatively, with a non-generic holder class (note that <code>Fix</code> is now a method, as properties cannot be generic): |
||
< |
<syntaxhighlight lang="csharp">static class YCombinator |
||
{ |
{ |
||
private delegate Func<T, TResult> RecursiveFunc<T, TResult>(RecursiveFunc<T, TResult> r); |
private delegate Func<T, TResult> RecursiveFunc<T, TResult>(RecursiveFunc<T, TResult> r); |
||
Line 1,184: | Line 1,184: | ||
public static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f) |
public static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f) |
||
=> ((RecursiveFunc<T, TResult>)(g => f(x => g(g)(x))))(g => f(x => g(g)(x))); |
=> ((RecursiveFunc<T, TResult>)(g => f(x => g(g)(x))))(g => f(x => g(g)(x))); |
||
}</ |
}</syntaxhighlight> |
||
Using the late-binding offered by <code>dynamic</code> to eliminate the recursive type: |
Using the late-binding offered by <code>dynamic</code> to eliminate the recursive type: |
||
< |
<syntaxhighlight lang="csharp">static class YCombinator<T, TResult> |
||
{ |
{ |
||
public static Func<Func<Func<T, TResult>, Func<T, TResult>>, Func<T, TResult>> Fix { get; } = |
public static Func<Func<Func<T, TResult>, Func<T, TResult>>, Func<T, TResult>> Fix { get; } = |
||
f => ((Func<dynamic, Func<T, TResult>>)(g => f(x => g(g)(x))))((Func<dynamic, Func<T, TResult>>)(g => f(x => g(g)(x)))); |
f => ((Func<dynamic, Func<T, TResult>>)(g => f(x => g(g)(x))))((Func<dynamic, Func<T, TResult>>)(g => f(x => g(g)(x)))); |
||
}</ |
}</syntaxhighlight> |
||
The usual version using recursion, disallowed by the task (implemented as a generic method): |
The usual version using recursion, disallowed by the task (implemented as a generic method): |
||
< |
<syntaxhighlight lang="csharp">static class YCombinator |
||
{ |
{ |
||
static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f) => x => f(Fix(f))(x); |
static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f) => x => f(Fix(f))(x); |
||
}</ |
}</syntaxhighlight> |
||
===Translations=== |
===Translations=== |
||
Line 1,206: | Line 1,206: | ||
'''Verbatim''' |
'''Verbatim''' |
||
< |
<syntaxhighlight lang="csharp">using Func = System.Func<int, int>; |
||
using FuncFunc = System.Func<System.Func<int, int>, System.Func<int, int>>; |
using FuncFunc = System.Func<System.Func<int, int>, System.Func<int, int>>; |
||
Line 1,246: | Line 1,246: | ||
return 0; |
return 0; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
'''Semi-idiomatic''' |
'''Semi-idiomatic''' |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using FuncFunc = System.Func<System.Func<int, int>, System.Func<int, int>>; |
using FuncFunc = System.Func<System.Func<int, int>, System.Func<int, int>>; |
||
Line 1,275: | Line 1,275: | ||
Console.WriteLine("fac(10) = " + fac(10)); |
Console.WriteLine("fac(10) = " + fac(10)); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
====[http://rosettacode.org/mw/index.php?oldid=287744#Ceylon Ceylon]==== |
====[http://rosettacode.org/mw/index.php?oldid=287744#Ceylon Ceylon]==== |
||
Line 1,283: | Line 1,283: | ||
'''Verbatim''' |
'''Verbatim''' |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Diagnostics; |
using System.Diagnostics; |
||
Line 1,330: | Line 1,330: | ||
Console.WriteLine(fibY1(10)); // 110 |
Console.WriteLine(fibY1(10)); // 110 |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
'''Semi-idiomatic''' |
'''Semi-idiomatic''' |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Diagnostics; |
using System.Diagnostics; |
||
Line 1,376: | Line 1,376: | ||
Console.WriteLine(fibY1(10)); |
Console.WriteLine(fibY1(10)); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
====[http://rosettacode.org/mw/index.php?oldid=287744#Go Go]==== |
====[http://rosettacode.org/mw/index.php?oldid=287744#Go Go]==== |
||
Line 1,382: | Line 1,382: | ||
'''Verbatim''' |
'''Verbatim''' |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
// Func and FuncFunc can be defined using using aliases and the System.Func<T, TReult> type, but RecursiveFunc must be a delegate type of its own. |
// Func and FuncFunc can be defined using using aliases and the System.Func<T, TReult> type, but RecursiveFunc must be a delegate type of its own. |
||
Line 1,424: | Line 1,424: | ||
}; |
}; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Recursive: |
Recursive: |
||
< |
<syntaxhighlight lang="csharp"> static Func Y(FuncFunc f) { |
||
return delegate (int x) { |
return delegate (int x) { |
||
return f(Y(f))(x); |
return f(Y(f))(x); |
||
}; |
}; |
||
}</ |
}</syntaxhighlight> |
||
'''Semi-idiomatic''' |
'''Semi-idiomatic''' |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
delegate int Func(int i); |
delegate int Func(int i); |
||
Line 1,456: | Line 1,456: | ||
static Func almost_fib(Func f) => x => x <= 2 ? 1 : f(x - 1) + f(x - 2); |
static Func almost_fib(Func f) => x => x <= 2 ? 1 : f(x - 1) + f(x - 2); |
||
}</ |
}</syntaxhighlight> |
||
Recursive: |
Recursive: |
||
< |
<syntaxhighlight lang="csharp"> static Func Y(FuncFunc f) => x => f(Y(f))(x);</syntaxhighlight> |
||
====[http://rosettacode.org/mw/index.php?oldid=287744#Java Java]==== |
====[http://rosettacode.org/mw/index.php?oldid=287744#Java Java]==== |
||
Line 1,466: | Line 1,466: | ||
Since Java uses interfaces and C# uses delegates, which are the only type that the C# compiler will coerce lambda expressions to, this code declares a <code>Functions</code> class for providing a means of converting CLR delegates to objects that implement the <code>Function</code> and <code>RecursiveFunction</code> interfaces. |
Since Java uses interfaces and C# uses delegates, which are the only type that the C# compiler will coerce lambda expressions to, this code declares a <code>Functions</code> class for providing a means of converting CLR delegates to objects that implement the <code>Function</code> and <code>RecursiveFunction</code> interfaces. |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
static class Program { |
static class Program { |
||
Line 1,514: | Line 1,514: | ||
Console.WriteLine("fac(10) = " + fac.apply(10)); |
Console.WriteLine("fac(10) = " + fac.apply(10)); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
'''"Idiomatic"''' |
'''"Idiomatic"''' |
||
For demonstrative purposes, to completely avoid using CLR delegates, lambda expressions can be replaced with explicit types that implement the functional interfaces. Closures are thus implemented by replacing all usages of the original local variable with a field of the type that represents the lambda expression; this process, called "hoisting" is actually how variable capturing is implemented by the C# compiler (for more information, see [https://blogs.msdn.microsoft.com/abhinaba/2005/10/18/c-anonymous-methods-are-not-closures/ this Microsoft blog post]. |
For demonstrative purposes, to completely avoid using CLR delegates, lambda expressions can be replaced with explicit types that implement the functional interfaces. Closures are thus implemented by replacing all usages of the original local variable with a field of the type that represents the lambda expression; this process, called "hoisting" is actually how variable capturing is implemented by the C# compiler (for more information, see [https://blogs.msdn.microsoft.com/abhinaba/2005/10/18/c-anonymous-methods-are-not-closures/ this Microsoft blog post]. |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
static class YCombinator { |
static class YCombinator { |
||
Line 1,609: | Line 1,609: | ||
Console.WriteLine("fac(10) = " + fac.apply(10)); |
Console.WriteLine("fac(10) = " + fac.apply(10)); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
'''C# 1.0''' |
'''C# 1.0''' |
||
To conclude this chain of decreasing reliance on language features, here is above code translated to C# 1.0. The largest change is the replacement of the generic interfaces with the results of manually substituting their type parameters. |
To conclude this chain of decreasing reliance on language features, here is above code translated to C# 1.0. The largest change is the replacement of the generic interfaces with the results of manually substituting their type parameters. |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
class Program { |
class Program { |
||
Line 1,710: | Line 1,710: | ||
Console.WriteLine("fac(10) = " + fac.apply(10)); |
Console.WriteLine("fac(10) = " + fac.apply(10)); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
'''Modified/varargs (the last implementation in the Java section)''' |
'''Modified/varargs (the last implementation in the Java section)''' |
||
Line 1,716: | Line 1,716: | ||
Since C# delegates cannot declare members, extension methods are used to simulate doing so. |
Since C# delegates cannot declare members, extension methods are used to simulate doing so. |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Collections.Generic; |
using System.Collections.Generic; |
||
using System.Linq; |
using System.Linq; |
||
Line 1,844: | Line 1,844: | ||
).ForAll(Console.WriteLine); |
).ForAll(Console.WriteLine); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
====[http://rosettacode.org/mw/index.php?oldid=287744#Swift Swift]==== |
====[http://rosettacode.org/mw/index.php?oldid=287744#Swift Swift]==== |
||
Line 1,852: | Line 1,852: | ||
The more idiomatic version doesn't look much different. |
The more idiomatic version doesn't look much different. |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
static class Program { |
static class Program { |
||
Line 1,872: | Line 1,872: | ||
Console.WriteLine($"fib(9) = {fib(9)}"); |
Console.WriteLine($"fib(9) = {fib(9)}"); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Without recursive type: |
Without recursive type: |
||
< |
<syntaxhighlight lang="csharp"> public static Func<A, B> Y<A, B>(Func<Func<A, B>, Func<A, B>> f) { |
||
Func<dynamic, Func<A, B>> r = z => { var w = (Func<dynamic, Func<A, B>>)z; return f(_0 => w(w)(_0)); }; |
Func<dynamic, Func<A, B>> r = z => { var w = (Func<dynamic, Func<A, B>>)z; return f(_0 => w(w)(_0)); }; |
||
return r(r); |
return r(r); |
||
}</ |
}</syntaxhighlight> |
||
Recursive: |
Recursive: |
||
< |
<syntaxhighlight lang="csharp"> public static Func<In, Out> Y<In, Out>(Func<Func<In, Out>, Func<In, Out>> f) { |
||
return x => f(Y(f))(x); |
return x => f(Y(f))(x); |
||
}</ |
}</syntaxhighlight> |
||
=={{header|C++}}== |
=={{header|C++}}== |
||
Line 1,889: | Line 1,889: | ||
Known to work with GCC 4.7.2. Compile with |
Known to work with GCC 4.7.2. Compile with |
||
g++ --std=c++11 ycomb.cc |
g++ --std=c++11 ycomb.cc |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
#include <functional> |
#include <functional> |
||
Line 1,931: | Line 1,931: | ||
std::cout << "fac(10) = " << fac(10) << std::endl; |
std::cout << "fac(10) = " << fac(10) << std::endl; |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,942: | Line 1,942: | ||
A shorter version, taking advantage of generic lambdas. Known to work with GCC 5.2.0, but likely some earlier versions as well. Compile with |
A shorter version, taking advantage of generic lambdas. Known to work with GCC 5.2.0, but likely some earlier versions as well. Compile with |
||
g++ --std=c++14 ycomb.cc |
g++ --std=c++14 ycomb.cc |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
#include <functional> |
#include <functional> |
||
int main () { |
int main () { |
||
Line 1,962: | Line 1,962: | ||
std:: cout << fib (10) << '\n' |
std:: cout << fib (10) << '\n' |
||
<< fac (10) << '\n'; |
<< fac (10) << '\n'; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,971: | Line 1,971: | ||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="cpp">template <typename A, typename B> |
||
std::function<B(A)> Y (std::function<std::function<B(A)>(std::function<B(A)>)> f) { |
std::function<B(A)> Y (std::function<std::function<B(A)>(std::function<B(A)>)> f) { |
||
return [f](A x) { |
return [f](A x) { |
||
return f(Y(f))(x); |
return f(Y(f))(x); |
||
}; |
}; |
||
}</ |
}</syntaxhighlight> |
||
Another version which is disallowed because a function passes itself, which is also a kind of recursion: |
Another version which is disallowed because a function passes itself, which is also a kind of recursion: |
||
< |
<syntaxhighlight lang="cpp">template <typename A, typename B> |
||
struct YFunctor { |
struct YFunctor { |
||
const std::function<std::function<B(A)>(std::function<B(A)>)> f; |
const std::function<std::function<B(A)>(std::function<B(A)>)> f; |
||
Line 1,991: | Line 1,991: | ||
std::function<B(A)> Y (std::function<std::function<B(A)>(std::function<B(A)>)> f) { |
std::function<B(A)> Y (std::function<std::function<B(A)>(std::function<B(A)>)> f) { |
||
return YFunctor<A,B>(f); |
return YFunctor<A,B>(f); |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Ceylon}}== |
=={{header|Ceylon}}== |
||
Using a class for the recursive type: |
Using a class for the recursive type: |
||
< |
<syntaxhighlight lang="ceylon">Result(*Args) y1<Result,Args>( |
||
Result(*Args)(Result(*Args)) f) |
Result(*Args)(Result(*Args)) f) |
||
given Args satisfies Anything[] { |
given Args satisfies Anything[] { |
||
Line 2,016: | Line 2,016: | ||
print(factorialY1(10)); // 3628800 |
print(factorialY1(10)); // 3628800 |
||
print(fibY1(10)); // 110</ |
print(fibY1(10)); // 110</syntaxhighlight> |
||
Using Anything to erase the function type: |
Using Anything to erase the function type: |
||
< |
<syntaxhighlight lang="ceylon">Result(*Args) y2<Result,Args>( |
||
Result(*Args)(Result(*Args)) f) |
Result(*Args)(Result(*Args)) f) |
||
given Args satisfies Anything[] { |
given Args satisfies Anything[] { |
||
Line 2,029: | Line 2,029: | ||
return r(r); |
return r(r); |
||
}</ |
}</syntaxhighlight> |
||
Using recursion, this does not satisfy the task requirements, but is included here for illustrative purposes: |
Using recursion, this does not satisfy the task requirements, but is included here for illustrative purposes: |
||
< |
<syntaxhighlight lang="ceylon">Result(*Args) y3<Result, Args>( |
||
Result(*Args)(Result(*Args)) f) |
Result(*Args)(Result(*Args)) f) |
||
given Args satisfies Anything[] |
given Args satisfies Anything[] |
||
=> flatten((Args args) => f(y3(f))(*args));</ |
=> flatten((Args args) => f(y3(f))(*args));</syntaxhighlight> |
||
=={{header|Chapel}}== |
=={{header|Chapel}}== |
||
Line 2,042: | Line 2,042: | ||
{{works with|Chapel version 1.24.1}} |
{{works with|Chapel version 1.24.1}} |
||
< |
<syntaxhighlight lang="chapel">proc fixz(f) { |
||
record InnerFunc { |
record InnerFunc { |
||
const xi; |
const xi; |
||
Line 2,077: | Line 2,077: | ||
writeln(facz(10)); |
writeln(facz(10)); |
||
writeln(fibz(10));</ |
writeln(fibz(10));</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>3628800 |
<pre>3628800 |
||
Line 2,085: | Line 2,085: | ||
{{works with|Chapel version 1.24.1}} |
{{works with|Chapel version 1.24.1}} |
||
< |
<syntaxhighlight lang="chapel">// this is the longer version... |
||
/* |
/* |
||
proc fixy(f) { |
proc fixy(f) { |
||
Line 2,132: | Line 2,132: | ||
writeln(facy(10)); |
writeln(facy(10)); |
||
writeln(fibz(10));</ |
writeln(fibz(10));</syntaxhighlight> |
||
The output is the same as the above. |
The output is the same as the above. |
||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
< |
<syntaxhighlight lang="lisp">(defn Y [f] |
||
((fn [x] (x x)) |
((fn [x] (x x)) |
||
(fn [x] |
(fn [x] |
||
Line 2,154: | Line 2,154: | ||
1 1 |
1 1 |
||
(+ (f (dec n)) |
(+ (f (dec n)) |
||
(f (dec (dec n))))))))</ |
(f (dec (dec n))))))))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,164: | Line 2,164: | ||
<code>Y</code> can be written slightly more concisely via syntax sugar: |
<code>Y</code> can be written slightly more concisely via syntax sugar: |
||
< |
<syntaxhighlight lang="lisp">(defn Y [f] |
||
(#(% %) #(f (fn [& args] (apply (% %) args)))))</ |
(#(% %) #(f (fn [& args] (apply (% %) args)))))</syntaxhighlight> |
||
=={{header|CoffeeScript}}== |
=={{header|CoffeeScript}}== |
||
< |
<syntaxhighlight lang="coffeescript">Y = (f) -> g = f( (t...) -> g(t...) )</syntaxhighlight> |
||
or |
or |
||
< |
<syntaxhighlight lang="coffeescript">Y = (f) -> ((h)->h(h))((h)->f((t...)->h(h)(t...)))</syntaxhighlight> |
||
< |
<syntaxhighlight lang="coffeescript">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 ) |
fib = Y( (f) -> (n) -> if n > 1 then f(n-1) + f(n-2) else n ) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
< |
<syntaxhighlight lang="lisp">(defun Y (f) |
||
((lambda (g) (funcall g g)) |
((lambda (g) (funcall g g)) |
||
(lambda (g) |
(lambda (g) |
||
Line 2,204: | Line 2,204: | ||
? (mapcar #'fib '(1 2 3 4 5 6 7 8 9 10)) |
? (mapcar #'fib '(1 2 3 4 5 6 7 8 9 10)) |
||
(1 1 2 3 5 8 13 21 34 55)</ |
(1 1 2 3 5 8 13 21 34 55)</syntaxhighlight> |
||
=={{header|Crystal}}== |
=={{header|Crystal}}== |
||
Line 2,212: | Line 2,212: | ||
The following Crystal code implements the name-recursion Y-Combinator without assuming that functions are recursive (which in Crystal they actually are): |
The following Crystal code implements the name-recursion Y-Combinator without assuming that functions are recursive (which in Crystal they actually are): |
||
< |
<syntaxhighlight lang="crystal">require "big" |
||
struct RecursiveFunc(T) # a generic recursive function wrapper... |
struct RecursiveFunc(T) # a generic recursive function wrapper... |
||
Line 2,242: | Line 2,242: | ||
puts fac(10) |
puts fac(10) |
||
puts fib(11) # starts from 0 not 1!</ |
puts fib(11) # starts from 0 not 1!</syntaxhighlight> |
||
The "horrendously inefficient" massively repetitious implementations can be made much more efficient by changing the implementation for the two functions as follows: |
The "horrendously inefficient" massively repetitious implementations can be made much more efficient by changing the implementation for the two functions as follows: |
||
< |
<syntaxhighlight lang="crystal">def fac(x) # the more efficient tail recursive version... |
||
facp = -> (fn : Proc(BigInt -> (Int32 -> BigInt))) { |
facp = -> (fn : Proc(BigInt -> (Int32 -> BigInt))) { |
||
-> (n : BigInt) { -> (i : Int32) { |
-> (n : BigInt) { -> (i : Int32) { |
||
Line 2,258: | Line 2,258: | ||
i < 2 ? f : fn.call.call(s).call(f + s).call(i - 1) } } } } |
i < 2 ? f : fn.call.call(s).call(f + s).call(i - 1) } } } } |
||
YCombo.new(fibp).fixy.call(BigInt.new).call(BigInt.new(1)).call(x) |
YCombo.new(fibp).fixy.call(BigInt.new).call(BigInt.new(1)).call(x) |
||
end</ |
end</syntaxhighlight> |
||
Finally, since Crystal function's/"def"'s can call themselves recursively, the implementation of the Y-Combinator can be changed to use this while still being "call by name" (not value/variable recursion) as follows; this uses the identical lambda "Proc"'s internally with just the application to the Y-Combinator changed: |
Finally, since Crystal function's/"def"'s can call themselves recursively, the implementation of the Y-Combinator can be changed to use this while still being "call by name" (not value/variable recursion) as follows; this uses the identical lambda "Proc"'s internally with just the application to the Y-Combinator changed: |
||
< |
<syntaxhighlight lang="crystal">def ycombo(f) |
||
f.call(-> { ycombo(f) }) |
f.call(-> { ycombo(f) }) |
||
end |
end |
||
Line 2,278: | Line 2,278: | ||
i < 2 ? f : fn.call.call(s).call(f + s).call(i - 1) } } } } |
i < 2 ? f : fn.call.call(s).call(f + s).call(i - 1) } } } } |
||
ycombo(fibp).call(BigInt.new).call(BigInt.new(1)).call(x) |
ycombo(fibp).call(BigInt.new).call(BigInt.new(1)).call(x) |
||
end</ |
end</syntaxhighlight> |
||
All versions produce the same output: |
All versions produce the same output: |
||
Line 2,287: | Line 2,287: | ||
=={{header|D}}== |
=={{header|D}}== |
||
A stateless generic Y combinator: |
A stateless generic Y combinator: |
||
< |
<syntaxhighlight lang="d">import std.stdio, std.traits, std.algorithm, std.range; |
||
auto Y(S, T...)(S delegate(T) delegate(S delegate(T)) f) { |
auto Y(S, T...)(S delegate(T) delegate(S delegate(T)) f) { |
||
Line 2,311: | Line 2,311: | ||
writeln("factorial: ", 10.iota.map!factorial); |
writeln("factorial: ", 10.iota.map!factorial); |
||
writeln("ackermann(3, 5): ", ackermann(3, 5)); |
writeln("ackermann(3, 5): ", ackermann(3, 5)); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>factorial: [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880] |
<pre>factorial: [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880] |
||
Line 2,321: | Line 2,321: | ||
{{trans|C++}} |
{{trans|C++}} |
||
(The translation is not literal; e.g. the function argument type is left unspecified to increase generality.) |
(The translation is not literal; e.g. the function argument type is left unspecified to increase generality.) |
||
< |
<syntaxhighlight lang="delphi">program Y; |
||
{$APPTYPE CONSOLE} |
{$APPTYPE CONSOLE} |
||
Line 2,387: | Line 2,387: | ||
Writeln ('Fib(10) = ', Fib (10)); |
Writeln ('Fib(10) = ', Fib (10)); |
||
Writeln ('Fac(10) = ', Fac (10)); |
Writeln ('Fac(10) = ', Fac (10)); |
||
end.</ |
end.</syntaxhighlight> |
||
=={{header|Dhall}}== |
=={{header|Dhall}}== |
||
Line 2,395: | Line 2,395: | ||
Here's an example using Natural/Fold to define recursive definitions of fibonacci and factorial: |
Here's an example using Natural/Fold to define recursive definitions of fibonacci and factorial: |
||
< |
<syntaxhighlight lang="dhall">let const |
||
: ∀(b : Type) → ∀(a : Type) → a → b → a |
: ∀(b : Type) → ∀(a : Type) → a → b → a |
||
= λ(r : Type) → λ(a : Type) → λ(x : a) → λ(y : r) → x |
= λ(r : Type) → λ(a : Type) → λ(x : a) → λ(y : r) → x |
||
Line 2,439: | Line 2,439: | ||
n |
n |
||
in [fac 50, fib 50]</ |
in [fac 50, fib 50]</syntaxhighlight> |
||
The above dhall file gets rendered down to: |
The above dhall file gets rendered down to: |
||
< |
<syntaxhighlight lang="dhall">[ 30414093201713378043612608166064768844377641568960512000000000000 |
||
, 12586269025 |
, 12586269025 |
||
]</ |
]</syntaxhighlight> |
||
=={{header|Déjà Vu}}== |
=={{header|Déjà Vu}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
< |
<syntaxhighlight lang="dejavu">Y f: |
||
labda y: |
labda y: |
||
labda: |
labda: |
||
Line 2,475: | Line 2,475: | ||
!. fac 6 |
!. fac 6 |
||
!. fib 6</ |
!. fib 6</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>720 |
<pre>720 |
||
Line 2,482: | Line 2,482: | ||
=={{header|E}}== |
=={{header|E}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
< |
<syntaxhighlight lang="e">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 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) } }}</ |
def fib := fn f { fn n { if (n == 0) {0} else if (n == 1) {1} else { f(n-1) + f(n-2) } }}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="e">? pragma.enable("accumulator") |
||
? accum [] for i in 0..!10 { _.with(y(fac)(i)) } |
? accum [] for i in 0..!10 { _.with(y(fac)(i)) } |
||
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880] |
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880] |
||
? accum [] for i in 0..!10 { _.with(y(fib)(i)) } |
? accum [] for i in 0..!10 { _.with(y(fib)(i)) } |
||
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]</ |
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]</syntaxhighlight> |
||
=={{header|EchoLisp}}== |
=={{header|EchoLisp}}== |
||
< |
<syntaxhighlight lang="scheme"> |
||
;; Ref : http://www.ece.uc.edu/~franco/C511/html/Scheme/ycomb.html |
;; Ref : http://www.ece.uc.edu/~franco/C511/html/Scheme/ycomb.html |
||
Line 2,518: | Line 2,518: | ||
(fact 10) |
(fact 10) |
||
→ 3628800 |
→ 3628800 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Eero}}== |
=={{header|Eero}}== |
||
Translated from Objective-C example on this page. |
Translated from Objective-C example on this page. |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
typedef int (^Func)(int) |
typedef int (^Func)(int) |
||
Line 2,550: | Line 2,550: | ||
Log('fac(10) = %d', fac(10)) |
Log('fac(10) = %d', fac(10)) |
||
return 0</ |
return 0</syntaxhighlight> |
||
=={{header|Ela}}== |
=={{header|Ela}}== |
||
< |
<syntaxhighlight lang="ela">fix = \f -> (\x -> & f (x x)) (\x -> & f (x x)) |
||
fac _ 0 = 1 |
fac _ 0 = 1 |
||
Line 2,562: | Line 2,562: | ||
fib f n = f (n - 1) + f (n - 2) |
fib f n = f (n - 1) + f (n - 2) |
||
(fix fac 12, fix fib 12)</ |
(fix fac 12, fix fib 12)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,570: | Line 2,570: | ||
{{trans|Smalltalk}} |
{{trans|Smalltalk}} |
||
ELENA 4.x : |
ELENA 4.x : |
||
< |
<syntaxhighlight lang="elena">import extensions; |
||
singleton YCombinator |
singleton YCombinator |
||
Line 2,585: | Line 2,585: | ||
console.printLine("fib(10)=",fib(10)); |
console.printLine("fib(10)=",fib(10)); |
||
console.printLine("fact(10)=",fact(10)); |
console.printLine("fact(10)=",fact(10)); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,594: | Line 2,594: | ||
=={{header|Elixir}}== |
=={{header|Elixir}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
< |
<syntaxhighlight lang="elixir"> |
||
iex(1)> yc = fn f -> (fn x -> x.(x) end).(fn y -> f.(fn arg -> y.(y).(arg) end) end) end |
iex(1)> yc = fn f -> (fn x -> x.(x) end).(fn y -> f.(fn arg -> y.(y).(arg) end) end) end |
||
#Function<6.90072148/1 in :erl_eval.expr/5> |
#Function<6.90072148/1 in :erl_eval.expr/5> |
||
Line 2,605: | Line 2,605: | ||
iex(5)> for i <- 0..9, do: yc.(fib).(i) |
iex(5)> for i <- 0..9, do: yc.(fib).(i) |
||
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34] |
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34] |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Elm}}== |
=={{header|Elm}}== |
||
Line 2,613: | Line 2,613: | ||
Note: the Fibonacci sequence is defined to start with zero or one, with the first exactly the same but with a zero prepended; these Fibonacci calculations use the second definition. |
Note: the Fibonacci sequence is defined to start with zero or one, with the first exactly the same but with a zero prepended; these Fibonacci calculations use the second definition. |
||
< |
<syntaxhighlight lang="elm">module Main exposing ( main ) |
||
import Html exposing ( Html, text ) |
import Html exposing ( Html, text ) |
||
Line 2,687: | Line 2,687: | ||
++ " " ++ String.fromInt (facy 10) ++ " " ++ String.fromInt (fiby 10) |
++ " " ++ String.fromInt (facy 10) ++ " " ++ String.fromInt (fiby 10) |
||
++ " " ++ nCISs2String 20 (fibs()) |
++ " " ++ nCISs2String 20 (fibs()) |
||
|> text</ |
|> text</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>3628800 55 3628800 55 ( 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 )</pre> |
<pre>3628800 55 3628800 55 ( 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 )</pre> |
||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
< |
<syntaxhighlight lang="erlang">Y = fun(M) -> (fun(X) -> X(X) end)(fun (F) -> M(fun(A) -> (F(F))(A) end) end) end. |
||
Fac = fun (F) -> |
Fac = fun (F) -> |
||
Line 2,706: | Line 2,706: | ||
end. |
end. |
||
(Y(Fac))(5). %% 120 |
(Y(Fac))(5). %% 120 |
||
(Y(Fib))(8). %% 21</ |
(Y(Fib))(8). %% 21</syntaxhighlight> |
||
=={{header|F Sharp|F#}}== |
=={{header|F Sharp|F#}}== |
||
< |
<syntaxhighlight lang="fsharp">type 'a mu = Roll of ('a mu -> 'a) // ' fixes ease syntax colouring confusion with |
||
let unroll (Roll x) = x |
let unroll (Roll x) = x |
||
Line 2,743: | Line 2,743: | ||
fac 10 |> printfn "%A" // prints 3628800 |
fac 10 |> printfn "%A" // prints 3628800 |
||
fib 10 |> printfn "%A" // prints 55 |
fib 10 |> printfn "%A" // prints 55 |
||
0 // return an integer exit code</ |
0 // return an integer exit code</syntaxhighlight> |
||
{{output}} |
{{output}} |
||
<pre>3628800 |
<pre>3628800 |
||
Line 2,752: | Line 2,752: | ||
Also note that the above isn't the true fix point Y-combinator which would race without the beta conversion to the Z-combinator with the included `a` argument; the Z-combinator can't be used in all cases that require a true Y-combinator such as in the formation of deferred execution sequences in the last example, as follows: |
Also note that the above isn't the true fix point Y-combinator which would race without the beta conversion to the Z-combinator with the included `a` argument; the Z-combinator can't be used in all cases that require a true Y-combinator such as in the formation of deferred execution sequences in the last example, as follows: |
||
< |
<syntaxhighlight lang="fsharp">// same as previous... |
||
type 'a mu = Roll of ('a mu -> 'a) // ' fixes ease syntax colouring confusion with |
type 'a mu = Roll of ('a mu -> 'a) // ' fixes ease syntax colouring confusion with |
||
Line 2,791: | Line 2,791: | ||
fibs() |> Seq.take 20 |> Seq.iter (printf "%A ") |
fibs() |> Seq.take 20 |> Seq.iter (printf "%A ") |
||
printfn "" |
printfn "" |
||
0 // return an integer exit code</ |
0 // return an integer exit code</syntaxhighlight> |
||
{{output}} |
{{output}} |
||
<pre>3628800 |
<pre>3628800 |
||
Line 2,798: | Line 2,798: | ||
The above would be useful if F# did not have recursive functions (functions that can call themselves in their own definition), but as for most modern languages, F# does have function recursion by the use of the `rec` keyword before the function name, thus the above `fac` and `fib` functions can be written much more simply (and to run faster using tail recursion) with a recursion definition for the `fix` Y-combinator as follows, with a simple injected deferred execution to prevent race: |
The above would be useful if F# did not have recursive functions (functions that can call themselves in their own definition), but as for most modern languages, F# does have function recursion by the use of the `rec` keyword before the function name, thus the above `fac` and `fib` functions can be written much more simply (and to run faster using tail recursion) with a recursion definition for the `fix` Y-combinator as follows, with a simple injected deferred execution to prevent race: |
||
< |
<syntaxhighlight lang="fsharp">let rec fix f = f <| fun() -> fix f |
||
// val fix : f:((unit -> 'a) -> 'a) -> 'a |
// val fix : f:((unit -> 'a) -> 'a) -> 'a |
||
// the application of this true Y-combinator is the same as for the above non function recursive version.</ |
// the application of this true Y-combinator is the same as for the above non function recursive version.</syntaxhighlight> |
||
Using the Y-combinator (or Z-combinator) as expressed here is pointless as in unnecessary and makes the code slower due to the extra function calls through the call stack, with the first non-function recursive implementation even slower than the second function recursion one; a non Y-combinator version can use function recursion with tail call optimization to simplify looping for about 100 times the speed in the actual loop overhead; thus, this is primarily an intellectual exercise. |
Using the Y-combinator (or Z-combinator) as expressed here is pointless as in unnecessary and makes the code slower due to the extra function calls through the call stack, with the first non-function recursive implementation even slower than the second function recursion one; a non Y-combinator version can use function recursion with tail call optimization to simplify looping for about 100 times the speed in the actual loop overhead; thus, this is primarily an intellectual exercise. |
||
Line 2,809: | Line 2,809: | ||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
In rosettacode/Y.factor |
In rosettacode/Y.factor |
||
< |
<syntaxhighlight lang="factor">USING: fry kernel math ; |
||
IN: rosettacode.Y |
IN: rosettacode.Y |
||
: Y ( quot -- quot ) |
: Y ( quot -- quot ) |
||
Line 2,818: | Line 2,818: | ||
: almost-fib ( quot -- quot ) |
: almost-fib ( quot -- quot ) |
||
'[ dup 2 >= [ 1 2 [ - @ ] bi-curry@ bi + ] when ] ;</ |
'[ dup 2 >= [ 1 2 [ - @ ] bi-curry@ bi + ] when ] ;</syntaxhighlight> |
||
In rosettacode/Y-tests.factor |
In rosettacode/Y-tests.factor |
||
< |
<syntaxhighlight lang="factor">USING: kernel tools.test rosettacode.Y ; |
||
IN: rosettacode.Y.tests |
IN: rosettacode.Y.tests |
||
[ 120 ] [ 5 [ almost-fac ] Y call ] unit-test |
[ 120 ] [ 5 [ almost-fac ] Y call ] unit-test |
||
[ 8 ] [ 6 [ almost-fib ] Y call ] unit-test</ |
[ 8 ] [ 6 [ almost-fib ] Y call ] unit-test</syntaxhighlight> |
||
running the tests : |
running the tests : |
||
<pre> ( scratchpad - auto ) "rosettacode.Y" test |
<pre> ( scratchpad - auto ) "rosettacode.Y" test |
||
Line 2,832: | Line 2,832: | ||
=={{header|Falcon}}== |
=={{header|Falcon}}== |
||
<syntaxhighlight lang="falcon"> |
|||
<lang Falcon> |
|||
Y = { f => {x=> {n => f(x(x))(n)}} ({x=> {n => f(x(x))(n)}}) } |
Y = { f => {x=> {n => f(x(x))(n)}} ({x=> {n => f(x(x))(n)}}) } |
||
facStep = { f => {x => x < 1 ? 1 : x*f(x-1) }} |
facStep = { f => {x => x < 1 ? 1 : x*f(x-1) }} |
||
Line 2,842: | Line 2,842: | ||
> "Factorial 10: ", YFac(10) |
> "Factorial 10: ", YFac(10) |
||
> "Fibonacci 10: ", YFib(10) |
> "Fibonacci 10: ", YFib(10) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
< |
<syntaxhighlight lang="forth">\ Address of an xt. |
||
variable 'xt |
variable 'xt |
||
\ Make room for an xt. |
\ Make room for an xt. |
||
Line 2,856: | Line 2,856: | ||
: y, ( xt1 -- xt2 ) >r :noname @xt, r> compile, postpone ; ; |
: y, ( xt1 -- xt2 ) >r :noname @xt, r> compile, postpone ; ; |
||
\ Make a new instance of the Y combinator. |
\ Make a new instance of the Y combinator. |
||
: y ( xt1 -- xt2 ) xt, y, dup !xt ;</ |
: y ( xt1 -- xt2 ) xt, y, dup !xt ;</syntaxhighlight> |
||
Samples: |
Samples: |
||
< |
<syntaxhighlight lang="forth">\ Factorial |
||
10 :noname ( u1 xt -- u2 ) over ?dup if 1- swap execute * else 2drop 1 then ; |
10 :noname ( u1 xt -- u2 ) over ?dup if 1- swap execute * else 2drop 1 then ; |
||
y execute . 3628800 ok |
y execute . 3628800 ok |
||
Line 2,866: | Line 2,866: | ||
10 :noname ( u1 xt -- u2 ) over 2 < if drop else >r 1- dup r@ execute swap 1- r> execute + then ; |
10 :noname ( u1 xt -- u2 ) over 2 < if drop else >r 1- dup r@ execute swap 1- r> execute + then ; |
||
y execute . 55 ok |
y execute . 55 ok |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
FreeBASIC does not support nested functions, lambda expressions or functions inside nested types |
FreeBASIC does not support nested functions, lambda expressions or functions inside nested types |
||
< |
<syntaxhighlight lang="freebasic">Function Y(f As String) As String |
||
Y = f |
Y = f |
||
End Function |
End Function |
||
Line 2,906: | Line 2,906: | ||
test("fac") |
test("fac") |
||
test("fib") |
test("fib") |
||
Sleep</ |
Sleep</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>fac: 1 2 6 24 120 720 5040 40320 362880 3628800 |
<pre>fac: 1 2 6 24 120 720 5040 40320 362880 3628800 |
||
Line 2,913: | Line 2,913: | ||
=={{header|GAP}}== |
=={{header|GAP}}== |
||
< |
<syntaxhighlight lang="gap">Y := function(f) |
||
local u; |
local u; |
||
u := x -> x(x); |
u := x -> x(x); |
||
Line 2,947: | Line 2,947: | ||
Y(fac)(8); |
Y(fac)(8); |
||
# 40320</ |
# 40320</syntaxhighlight> |
||
=={{header|Genyris}}== |
=={{header|Genyris}}== |
||
{{trans|Scheme}} |
{{trans|Scheme}} |
||
< |
<syntaxhighlight lang="genyris">def fac (f) |
||
function (n) |
function (n) |
||
if (equal? n 0) 1 |
if (equal? n 0) 1 |
||
Line 2,969: | Line 2,969: | ||
assertEqual ((Y fac) 5) 120 |
assertEqual ((Y fac) 5) 120 |
||
assertEqual ((Y fib) 8) 21</ |
assertEqual ((Y fib) 8) 21</syntaxhighlight> |
||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import "fmt" |
import "fmt" |
||
Line 3,012: | Line 3,012: | ||
return f(x-1)+f(x-2) |
return f(x-1)+f(x-2) |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 3,020: | Line 3,020: | ||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="go">func Y(f FuncFunc) Func { |
||
return func(x int) int { |
return func(x int) int { |
||
return f(Y(f))(x) |
return f(Y(f))(x) |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Groovy}}== |
=={{header|Groovy}}== |
||
Here is the simplest (unary) form of applicative order Y: |
Here is the simplest (unary) form of applicative order Y: |
||
< |
<syntaxhighlight lang="groovy">def Y = { le -> ({ f -> f(f) })({ f -> le { x -> f(f)(x) } }) } |
||
def factorial = Y { fac -> |
def factorial = Y { fac -> |
||
Line 3,040: | Line 3,040: | ||
} |
} |
||
assert fib(10) == 55</ |
assert fib(10) == 55</syntaxhighlight> |
||
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 '''''le'''ngth'' function. |
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 '''''le'''ngth'' function. |
||
A variadic version of Y in Groovy looks like this: |
A variadic version of Y in Groovy looks like this: |
||
< |
<syntaxhighlight lang="groovy">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 } } |
def mul = Y { mulStar -> { a, b -> a ? b + mulStar(a - 1, b) : 0 } } |
||
Line 3,050: | Line 3,050: | ||
1.upto(10) { |
1.upto(10) { |
||
assert mul(it, 10) == it * 10 |
assert mul(it, 10) == it * 10 |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
The obvious definition of the Y combinator <code>(\f-> (\x -> f (x x)) (\x-> f (x x)))</code> cannot be used in Haskell because it contains an infinite recursive type (<code>a = a -> b</code>). Defining a data type (Mu) allows this recursion to be broken. |
The obvious definition of the Y combinator <code>(\f-> (\x -> f (x x)) (\x-> f (x x)))</code> cannot be used in Haskell because it contains an infinite recursive type (<code>a = a -> b</code>). Defining a data type (Mu) allows this recursion to be broken. |
||
< |
<syntaxhighlight lang="haskell">newtype Mu a = Roll |
||
{ unroll :: Mu a -> a } |
{ unroll :: Mu a -> a } |
||
Line 3,099: | Line 3,099: | ||
[ map fac [1 .. 20] |
[ map fac [1 .. 20] |
||
, take 20 $ fibs() |
, take 20 $ fibs() |
||
]</ |
]</syntaxhighlight> |
||
The usual version uses recursion on a binding, disallowed by the task, to define the <code>fix</code> itself; but the definitions produced by this <code>fix</code> does ''not'' use recursion on value bindings although it does use recursion when defining a function (not possible in all languages), so it can be viewed as a true Y-combinator too: |
The usual version uses recursion on a binding, disallowed by the task, to define the <code>fix</code> itself; but the definitions produced by this <code>fix</code> does ''not'' use recursion on value bindings although it does use recursion when defining a function (not possible in all languages), so it can be viewed as a true Y-combinator too: |
||
< |
<syntaxhighlight lang="haskell">-- note that this version of fix uses function recursion in its own definition; |
||
-- thus its use just means that the recursion has been "pulled" into the "fix" function, |
-- thus its use just means that the recursion has been "pulled" into the "fix" function, |
||
-- instead of the function that uses it... |
-- instead of the function that uses it... |
||
Line 3,150: | Line 3,150: | ||
, map fib [1 .. 20] |
, map fib [1 .. 20] |
||
, take 20 fibs() |
, take 20 fibs() |
||
]</ |
]</syntaxhighlight> |
||
Now just because something is possible using the Y-combinator doesn't mean that it is practical: the above implementations can't compute much past the 1000th number in the Fibonacci list sequence and is quite slow at doing so; using direct function recursive routines compute about 100 times faster and don't hang for large ranges, nor give problems compiling as the first version does (GHC version 8.4.3 at -O1 optimization level). |
Now just because something is possible using the Y-combinator doesn't mean that it is practical: the above implementations can't compute much past the 1000th number in the Fibonacci list sequence and is quite slow at doing so; using direct function recursive routines compute about 100 times faster and don't hang for large ranges, nor give problems compiling as the first version does (GHC version 8.4.3 at -O1 optimization level). |
||
Line 3,161: | Line 3,161: | ||
===Non-tacit version=== |
===Non-tacit version=== |
||
Unfortunately, in principle, J functions cannot take functions of the same type as arguments. In other words, verbs (functions) cannot take verbs, and adverbs or conjunctions (higher-order functions) cannot take adverbs or conjunctions. This implementation uses the body, a literal (string), of an explicit adverb (a higher-order function with a left argument) as the argument for Y, to represent the adverb for which the product of Y is a fixed-point verb; Y itself is also an adverb. |
Unfortunately, in principle, J functions cannot take functions of the same type as arguments. In other words, verbs (functions) cannot take verbs, and adverbs or conjunctions (higher-order functions) cannot take adverbs or conjunctions. This implementation uses the body, a literal (string), of an explicit adverb (a higher-order function with a left argument) as the argument for Y, to represent the adverb for which the product of Y is a fixed-point verb; Y itself is also an adverb. |
||
< |
<syntaxhighlight lang="j">Y=. '('':''<@;(1;~":0)<@;<@((":0)&;))'(2 : 0 '') |
||
(1 : (m,'u'))(1 : (m,'''u u`:6('',(5!:5<''u''),'')`:6 y'''))(1 :'u u`:6') |
(1 : (m,'u'))(1 : (m,'''u u`:6('',(5!:5<''u''),'')`:6 y'''))(1 :'u u`:6') |
||
) |
) |
||
</syntaxhighlight> |
|||
</lang> |
|||
This Y combinator follows the standard method: it produces a fixed-point which reproduces and transforms itself anonymously according to the adverb represented by Y's argument. All names (variables) refer to arguments of the enclosing adverbs and there are no assignments. |
This Y combinator follows the standard method: it produces a fixed-point which reproduces and transforms itself anonymously according to the adverb represented by Y's argument. All names (variables) refer to arguments of the enclosing adverbs and there are no assignments. |
||
The factorial and Fibonacci examples follow: |
The factorial and Fibonacci examples follow: |
||
< |
<syntaxhighlight lang="j"> 'if. * y do. y * u <: y else. 1 end.' Y 10 NB. Factorial |
||
3628800 |
3628800 |
||
'(u@:<:@:<: + u@:<:)^:(1 < ])' Y 10 NB. Fibonacci |
'(u@:<:@:<: + u@:<:)^:(1 < ])' Y 10 NB. Fibonacci |
||
55</ |
55</syntaxhighlight> |
||
The names u, x, and y are J's standard names for arguments; the name y represents the argument of u and the name u represents the verb argument of the adverb for which Y produces a fixed-point. Any verb can also be expressed tacitly, without any reference to its argument(s), as in the Fibonacci example. |
The names u, x, and y are J's standard names for arguments; the name y represents the argument of u and the name u represents the verb argument of the adverb for which Y produces a fixed-point. Any verb can also be expressed tacitly, without any reference to its argument(s), as in the Fibonacci example. |
||
A structured derivation of a Y with states follows (the stateless version can be produced by replacing all the names by its referents): |
A structured derivation of a Y with states follows (the stateless version can be produced by replacing all the names by its referents): |
||
< |
<syntaxhighlight lang="j"> arb=. ':'<@;(1;~":0)<@;<@((":0)&;) NB. AR of an explicit adverb from its body |
||
ara=. 1 :'arb u' NB. The verb arb as an adverb |
ara=. 1 :'arb u' NB. The verb arb as an adverb |
||
Line 3,181: | Line 3,181: | ||
gab=. 1 :'u u`:6' NB. The AR of the adverb and the adverb itself as a train |
gab=. 1 :'u u`:6' NB. The AR of the adverb and the adverb itself as a train |
||
Y=. ara srt gab NB. Train of adverbs</ |
Y=. ara srt gab NB. Train of adverbs</syntaxhighlight> |
||
The adverb Y, apart from using a representation as Y's argument, satisfies the task's requirements. However, it only works for monadic verbs (functions with a right argument). J's verbs can also be dyadic (functions with a left and right arguments) and ambivalent (almost all J's primitive verbs are ambivalent; for example - can be used as in - 1 and 2 - 1). The following adverb (XY) implements anonymous recursion of monadic, dyadic, and ambivalent verbs (the name x represents the left argument of u), |
The adverb Y, apart from using a representation as Y's argument, satisfies the task's requirements. However, it only works for monadic verbs (functions with a right argument). J's verbs can also be dyadic (functions with a left and right arguments) and ambivalent (almost all J's primitive verbs are ambivalent; for example - can be used as in - 1 and 2 - 1). The following adverb (XY) implements anonymous recursion of monadic, dyadic, and ambivalent verbs (the name x represents the left argument of u), |
||
< |
<syntaxhighlight lang="j">XY=. (1 :'('':''<@;(1;~":0)<@;<@((":0)&;))u')(1 :'('':''<@;(1;~":0)<@;<@((":0)&;))((''u u`:6('',(5!:5<''u''),'')`:6 y''),(10{a.),'':'',(10{a.),''x(u u`:6('',(5!:5<''u''),'')`:6)y'')')(1 :'u u`:6')</syntaxhighlight> |
||
The following are examples of anonymous dyadic and ambivalent recursions, |
The following are examples of anonymous dyadic and ambivalent recursions, |
||
< |
<syntaxhighlight lang="j"> 1 2 3 '([:`(>:@:])`(<:@:[ u 1:)`(<:@[ u [ u <:@:])@.(#.@,&*))'XY"0/ 1 2 3 4 5 NB. Ackermann function... |
||
3 4 5 6 7 |
3 4 5 6 7 |
||
5 7 9 11 13 |
5 7 9 11 13 |
||
Line 3,198: | Line 3,198: | ||
8 11 20 41 86 179 368 |
8 11 20 41 86 179 368 |
||
NB. OEIS A097813 - main diagonal |
NB. OEIS A097813 - main diagonal |
||
NB. OEIS A050488 = A097813 - 1 - adyacent upper off-diagonal</ |
NB. OEIS A050488 = A097813 - 1 - adyacent upper off-diagonal</syntaxhighlight> |
||
J supports directly anonymous tacit recursion via the verb $: and for tacit recursions, XY is equivalent to the adverb, |
J supports directly anonymous tacit recursion via the verb $: and for tacit recursions, XY is equivalent to the adverb, |
||
< |
<syntaxhighlight lang="j">YX=. (1 :'('':''<@;(1;~":0)<@;<@((":0)&;))u')($:`)(`:6)</syntaxhighlight> |
||
===Tacit version=== |
===Tacit version=== |
||
The Y combinator can be implemented indirectly using, for example, the linear representations of verbs (Y becomes a wrapper which takes an ad hoc verb as an argument and serializes it; the underlying self-referring system interprets the serialized representation of a verb as the corresponding verb): |
The Y combinator can be implemented indirectly using, for example, the linear representations of verbs (Y becomes a wrapper which takes an ad hoc verb as an argument and serializes it; the underlying self-referring system interprets the serialized representation of a verb as the corresponding verb): |
||
< |
<syntaxhighlight lang="j">Y=. ((((&>)/)((((^:_1)b.)(`(<'0';_1)))(`:6)))(&([ 128!:2 ,&<)))</syntaxhighlight> |
||
The factorial and Fibonacci examples: |
The factorial and Fibonacci examples: |
||
< |
<syntaxhighlight lang="j"> u=. [ NB. Function (left) |
||
n=. ] NB. Argument (right) |
n=. ] NB. Argument (right) |
||
sr=. [ apply f. ,&< NB. Self referring |
sr=. [ apply f. ,&< NB. Self referring |
||
Line 3,217: | Line 3,217: | ||
Fib=. ((u sr n - 2:) + u sr n - 1:) ^: (1 < n) |
Fib=. ((u sr n - 2:) + u sr n - 1:) ^: (1 < n) |
||
Fib f. Y 10 |
Fib f. Y 10 |
||
55</ |
55</syntaxhighlight> |
||
The stateless functions are shown next (the f. adverb replaces all embedded names by its referents): |
The stateless functions are shown next (the f. adverb replaces all embedded names by its referents): |
||
< |
<syntaxhighlight lang="j"> fac f. Y NB. Factorial... |
||
'1:`(] * [ ([ 128!:2 ,&<) ] - 1:)@.(0 < ])&>/'&([ 128!:2 ,&<) |
'1:`(] * [ ([ 128!:2 ,&<) ] - 1:)@.(0 < ])&>/'&([ 128!:2 ,&<) |
||
Line 3,230: | Line 3,230: | ||
Fib f. NB. Fibonacci step... |
Fib f. NB. Fibonacci step... |
||
(([ ([ 128!:2 ,&<) ] - 2:) + [ ([ 128!:2 ,&<) ] - 1:)^:(1 < ])</ |
(([ ([ 128!:2 ,&<) ] - 2:) + [ ([ 128!:2 ,&<) ] - 1:)^:(1 < ])</syntaxhighlight> |
||
A structured derivation of Y follows: |
A structured derivation of Y follows: |
||
< |
<syntaxhighlight lang="j"> sr=. [ apply f.,&< NB. Self referring |
||
lv=. (((^:_1)b.)(`(<'0';_1)))(`:6) NB. Linear representation of a verb argument |
lv=. (((^:_1)b.)(`(<'0';_1)))(`:6) NB. Linear representation of a verb argument |
||
Y=. (&>)/lv(&sr) NB. Y with embedded states |
Y=. (&>)/lv(&sr) NB. Y with embedded states |
||
Y=. 'Y'f. NB. Fixing it... |
Y=. 'Y'f. NB. Fixing it... |
||
Y NB. ... To make it stateless (i.e., a combinator) |
Y NB. ... To make it stateless (i.e., a combinator) |
||
((((&>)/)((((^:_1)b.)(`_1))(`:6)))(&([ 128!:2 ,&<)))</ |
((((&>)/)((((^:_1)b.)(`_1))(`:6)))(&([ 128!:2 ,&<)))</syntaxhighlight> |
||
===Explicit alternate implementation=== |
===Explicit alternate implementation=== |
||
Line 3,243: | Line 3,243: | ||
Another approach: |
Another approach: |
||
< |
<syntaxhighlight lang="j">Y=:1 :0 |
||
f=. u Defer |
f=. u Defer |
||
(5!:1<'f') f y |
(5!:1<'f') f y |
||
Line 3,262: | Line 3,262: | ||
if. 2 > y do. y |
if. 2 > y do. y |
||
else. (x`:6 y-1) + x`:6 y-2 end. |
else. (x`:6 y-1) + x`:6 y-2 end. |
||
)</ |
)</syntaxhighlight> |
||
Example use: |
Example use: |
||
< |
<syntaxhighlight lang="j"> almost_factorial Y 9 |
||
362880 |
362880 |
||
almost_fibonacci Y 9 |
almost_fibonacci Y 9 |
||
34 |
34 |
||
almost_fibonacci Y"0 i. 10 |
almost_fibonacci Y"0 i. 10 |
||
0 1 1 2 3 5 8 13 21 34</ |
0 1 1 2 3 5 8 13 21 34</syntaxhighlight> |
||
Or, if you would prefer to not have a dependency on the definition of Defer, an equivalent expression would be: |
Or, if you would prefer to not have a dependency on the definition of Defer, an equivalent expression would be: |
||
< |
<syntaxhighlight lang="j">Y=:2 :0(0 :0) |
||
NB. this block will be n in the second part |
NB. this block will be n in the second part |
||
: |
: |
||
Line 3,283: | Line 3,283: | ||
f=. u (1 :n) |
f=. u (1 :n) |
||
(5!:1<'f') f y |
(5!:1<'f') f y |
||
)</ |
)</syntaxhighlight> |
||
That said, if you think of association with a name as state (because in different contexts the association may not exist, or may be different) you might also want to remove that association in the context of the Y combinator. |
That said, if you think of association with a name as state (because in different contexts the association may not exist, or may be different) you might also want to remove that association in the context of the Y combinator. |
||
Line 3,289: | Line 3,289: | ||
For example: |
For example: |
||
< |
<syntaxhighlight lang="j"> almost_factorial f. Y 10 |
||
3628800</ |
3628800</syntaxhighlight> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{works with|Java|8+}} |
{{works with|Java|8+}} |
||
< |
<syntaxhighlight lang="java5">import java.util.function.Function; |
||
public interface YCombinator { |
public interface YCombinator { |
||
Line 3,319: | Line 3,319: | ||
System.out.println("fac(10) = " + fac.apply(10)); |
System.out.println("fac(10) = " + fac.apply(10)); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 3,326: | Line 3,326: | ||
</pre> |
</pre> |
||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="java5"> public static <A,B> Function<A,B> Y(Function<Function<A,B>, Function<A,B>> f) { |
||
return x -> f.apply(Y(f)).apply(x); |
return x -> f.apply(Y(f)).apply(x); |
||
}</ |
}</syntaxhighlight> |
||
Another version which is disallowed because a function passes itself, which is also a kind of recursion: |
Another version which is disallowed because a function passes itself, which is also a kind of recursion: |
||
< |
<syntaxhighlight lang="java5"> public static <A,B> Function<A,B> Y(Function<Function<A,B>, Function<A,B>> f) { |
||
return new Function<A,B>() { |
return new Function<A,B>() { |
||
public B apply(A x) { |
public B apply(A x) { |
||
Line 3,337: | Line 3,337: | ||
} |
} |
||
}; |
}; |
||
}</ |
}</syntaxhighlight> |
||
{{works with|Java|pre-8}} |
{{works with|Java|pre-8}} |
||
We define a generic function interface like Java 8's <code>Function</code>. |
We define a generic function interface like Java 8's <code>Function</code>. |
||
< |
<syntaxhighlight lang="java5">interface Function<A, B> { |
||
public B call(A x); |
public B call(A x); |
||
} |
} |
||
Line 3,393: | Line 3,393: | ||
System.out.println("fac(10) = " + fac.call(10)); |
System.out.println("fac(10) = " + fac.call(10)); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
The following code modifies the Function interface such that multiple parameters (via varargs) are supported, simplifies the y function considerably, and the [[Ackermann function#Java|Ackermann function]] has been included in this implementation (mostly because both [[Y combinator#D|D]] and [[Y combinator#PicoLisp|PicoLisp]] include it in their own implementations). |
The following code modifies the Function interface such that multiple parameters (via varargs) are supported, simplifies the y function considerably, and the [[Ackermann function#Java|Ackermann function]] has been included in this implementation (mostly because both [[Y combinator#D|D]] and [[Y combinator#PicoLisp|PicoLisp]] include it in their own implementations). |
||
< |
<syntaxhighlight lang="java5">import java.util.function.Function; |
||
@FunctionalInterface |
@FunctionalInterface |
||
Line 3,404: | Line 3,404: | ||
return apply(this); |
return apply(this); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="java5">import java.util.function.Function; |
||
import java.util.function.UnaryOperator; |
import java.util.function.UnaryOperator; |
||
@FunctionalInterface |
@FunctionalInterface |
||
public interface FixedPoint<FUNCTION> extends Function<UnaryOperator<FUNCTION>, FUNCTION> {}</ |
public interface FixedPoint<FUNCTION> extends Function<UnaryOperator<FUNCTION>, FUNCTION> {}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="java5">import java.util.Arrays; |
||
import java.util.Optional; |
import java.util.Optional; |
||
import java.util.function.Function; |
import java.util.function.Function; |
||
Line 3,454: | Line 3,454: | ||
return inputs -> apply((INPUTS[]) Arrays.stream(inputs).parallel().map(transformer).toArray()); |
return inputs -> apply((INPUTS[]) Arrays.stream(inputs).parallel().map(transformer).toArray()); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="java5">import java.math.BigDecimal; |
||
import java.math.BigInteger; |
import java.math.BigInteger; |
||
import java.util.Arrays; |
import java.util.Arrays; |
||
Line 3,529: | Line 3,529: | ||
).forEach(System.out::println); |
).forEach(System.out::println); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} (may depend on which function gets processed first): |
{{out}} (may depend on which function gets processed first): |
||
<lang>factorial[10] = 3628800 |
<syntaxhighlight lang="text">factorial[10] = 3628800 |
||
ackermann[3, 2] = 29 |
ackermann[3, 2] = 29 |
||
fibonacci[20] = 6765</ |
fibonacci[20] = 6765</syntaxhighlight> |
||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
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: |
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: |
||
< |
<syntaxhighlight lang="javascript">function Y(f) { |
||
var g = f((function(h) { |
var g = f((function(h) { |
||
return function() { |
return function() { |
||
Line 3,563: | Line 3,563: | ||
return n > 1 ? f(n - 1) + f(n - 2) : n; |
return n > 1 ? f(n - 1) + f(n - 2) : n; |
||
}; |
}; |
||
});</ |
});</syntaxhighlight> |
||
Changing the order of function application (i.e. the place where <code>f</code> gets called) and making use of the fact that we're generating a fixed-point, this can be reduced to |
Changing the order of function application (i.e. the place where <code>f</code> gets called) and making use of the fact that we're generating a fixed-point, this can be reduced to |
||
< |
<syntaxhighlight lang="javascript">function Y(f) { |
||
return (function(h) { |
return (function(h) { |
||
return h(h); |
return h(h); |
||
Line 3,573: | Line 3,573: | ||
}); |
}); |
||
}); |
}); |
||
}</ |
}</syntaxhighlight> |
||
A functionally equivalent version using the implicit <code>this</code> parameter is also possible: |
A functionally equivalent version using the implicit <code>this</code> parameter is also possible: |
||
< |
<syntaxhighlight lang="javascript">function pseudoY(f) { |
||
return (function(h) { |
return (function(h) { |
||
return h(h); |
return h(h); |
||
Line 3,591: | Line 3,591: | ||
var fib = pseudoY(function(n) { |
var fib = pseudoY(function(n) { |
||
return n > 1 ? this(n - 1) + this(n - 2) : n; |
return n > 1 ? this(n - 1) + this(n - 2) : n; |
||
});</ |
});</syntaxhighlight> |
||
However, <code>pseudoY()</code> is not a fixed-point combinator. |
However, <code>pseudoY()</code> is not a fixed-point combinator. |
||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="javascript">function Y(f) { |
||
return function() { |
return function() { |
||
return f(Y(f)).apply(this, arguments); |
return f(Y(f)).apply(this, arguments); |
||
}; |
}; |
||
}</ |
}</syntaxhighlight> |
||
Another version which is disallowed because it uses <code>arguments.callee</code> for a function to get itself recursively: |
Another version which is disallowed because it uses <code>arguments.callee</code> for a function to get itself recursively: |
||
< |
<syntaxhighlight lang="javascript">function Y(f) { |
||
return function() { |
return function() { |
||
return f(arguments.callee).apply(this, arguments); |
return f(arguments.callee).apply(this, arguments); |
||
}; |
}; |
||
}</ |
}</syntaxhighlight> |
||
===ECMAScript 2015 (ES6) variants=== |
===ECMAScript 2015 (ES6) variants=== |
||
Since ECMAScript 2015 (ES6) just reached final draft, there are new ways to encode the applicative order Y combinator. |
Since ECMAScript 2015 (ES6) just reached final draft, there are new ways to encode the applicative order Y combinator. |
||
These use the new fat arrow function expression syntax, and are made to allow functions of more than one argument through the use of new rest parameters syntax and the corresponding new spread operator syntax. Also showcases new default parameter value syntax: |
These use the new fat arrow function expression syntax, and are made to allow functions of more than one argument through the use of new rest parameters syntax and the corresponding new spread operator syntax. Also showcases new default parameter value syntax: |
||
< |
<syntaxhighlight lang="javascript">let |
||
Y= // Except for the η-abstraction necessary for applicative order languages, this is the formal Y combinator. |
Y= // Except for the η-abstraction necessary for applicative order languages, this is the formal Y combinator. |
||
f=>((g=>(f((...x)=>g(g)(...x)))) |
f=>((g=>(f((...x)=>g(g)(...x)))) |
||
Line 3,629: | Line 3,629: | ||
fact=>(n,m=1)=>n<2?m:fact(n-1,n*m); |
fact=>(n,m=1)=>n<2?m:fact(n-1,n*m); |
||
tailfact= // Tail call version of factorial function |
tailfact= // Tail call version of factorial function |
||
Y(opentailfact);</ |
Y(opentailfact);</syntaxhighlight> |
||
ECMAScript 2015 (ES6) also permits a really compact polyvariadic variant for mutually recursive functions: |
ECMAScript 2015 (ES6) also permits a really compact polyvariadic variant for mutually recursive functions: |
||
< |
<syntaxhighlight lang="javascript">let |
||
polyfix= // A version that takes an array instead of multiple arguments would simply use l instead of (...l) for parameter |
polyfix= // A version that takes an array instead of multiple arguments would simply use l instead of (...l) for parameter |
||
(...l)=>( |
(...l)=>( |
||
Line 3,639: | Line 3,639: | ||
polyfix( |
polyfix( |
||
(even,odd)=>n=>(n===0)||odd(n-1), |
(even,odd)=>n=>(n===0)||odd(n-1), |
||
(even,odd)=>n=>(n!==0)&&even(n-1));</ |
(even,odd)=>n=>(n!==0)&&even(n-1));</syntaxhighlight> |
||
A minimalist version: |
A minimalist version: |
||
< |
<syntaxhighlight lang="javascript">var Y = f => (x => x(x))(y => f(x => y(y)(x))); |
||
var fac = Y(f => n => n > 1 ? n * f(n-1) : 1);</ |
var fac = Y(f => n => n > 1 ? n * f(n-1) : 1);</syntaxhighlight> |
||
=={{header|Joy}}== |
=={{header|Joy}}== |
||
<syntaxhighlight lang= |
<syntaxhighlight lang="joy">DEFINE y == [dup cons] swap concat dup cons i; |
||
fac == [[pop null] [pop succ] [[dup pred] dip i *] ifte] y.</syntaxhighlight> |
fac == [[pop null] [pop succ] [[dup pred] dip i *] ifte] y.</syntaxhighlight> |
||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia"> |
||
_ |
_ |
||
_ _ _(_)_ | Documentation: https://docs.julialang.org |
_ _ _(_)_ | Documentation: https://docs.julialang.org |
||
Line 3,670: | Line 3,670: | ||
Y = f -> (x -> x(x))(y -> f((t...) -> y(y)(t...))) |
Y = f -> (x -> x(x))(y -> f((t...) -> y(y)(t...))) |
||
Y |
Y |
||
</syntaxhighlight> |
|||
</lang> |
|||
Usage: |
Usage: |
||
< |
<syntaxhighlight lang="julia"> |
||
julia> fac = f -> (n -> n < 2 ? 1 : n * f(n - 1)) |
julia> fac = f -> (n -> n < 2 ? 1 : n * f(n - 1)) |
||
#9 (generic function with 1 method) |
#9 (generic function with 1 method) |
||
Line 3,706: | Line 3,706: | ||
34 |
34 |
||
55 |
55 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Kitten}}== |
=={{header|Kitten}}== |
||
< |
<syntaxhighlight lang="kitten">define y<S..., T...> (S..., (S..., (S... -> T...) -> T...) -> T...): |
||
-> f; { f y } f call |
-> f; { f y } f call |
||
Line 3,728: | Line 3,728: | ||
5 \fac y say // 120 |
5 \fac y say // 120 |
||
10 \fib y say // 55 |
10 \fib y say // 55 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Klingphix}}== |
=={{header|Klingphix}}== |
||
<syntaxhighlight lang="klingphix">:fac |
|||
<lang Klingphix>:fac |
|||
dup 1 great [dup 1 sub fac mult] if |
dup 1 great [dup 1 sub fac mult] if |
||
; |
; |
||
Line 3,751: | Line 3,751: | ||
@fac "fac" test |
@fac "fac" test |
||
"End " input</ |
"End " input</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>fib: 1 1 2 3 5 8 13 21 34 55 |
<pre>fib: 1 1 2 3 5 8 13 21 34 55 |
||
Line 3,758: | Line 3,758: | ||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
< |
<syntaxhighlight lang="scala">// version 1.1.2 |
||
typealias Func<T, R> = (T) -> R |
typealias Func<T, R> = (T) -> R |
||
Line 3,779: | Line 3,779: | ||
for (i in 1..10) print("${y(::fib)(i)} ") |
for (i in 1..10) print("${y(::fib)(i)} ") |
||
println() |
println() |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 3,790: | Line 3,790: | ||
Tested in http://lambdaway.free.fr/lambdawalks/?view=Ycombinator |
Tested in http://lambdaway.free.fr/lambdawalks/?view=Ycombinator |
||
<syntaxhighlight lang="scheme"> |
|||
<lang Scheme> |
|||
1) defining the Ycombinator |
1) defining the Ycombinator |
||
{def Y {lambda {:f} {:f :f}}} |
{def Y {lambda {:f} {:f :f}}} |
||
Line 3,815: | Line 3,815: | ||
-> 34 |
-> 34 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
< |
<syntaxhighlight lang="lua">Y = function (f) |
||
return function(...) |
return function(...) |
||
return (function(x) return x(x) end)(function(x) return f(function(y) return x(x)(y) end) end)(...) |
return (function(x) return x(x) end)(function(x) return f(function(y) return x(x)(y) end) end)(...) |
||
end |
end |
||
end |
end |
||
</syntaxhighlight> |
|||
</lang> |
|||
Usage: |
Usage: |
||
< |
<syntaxhighlight lang="lua">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 |
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) |
factorial, fibs = Y(almostfactorial), Y(almostfibs) |
||
print(factorial(7))</ |
print(factorial(7))</syntaxhighlight> |
||
=={{header|M2000 Interpreter}}== |
=={{header|M2000 Interpreter}}== |
||
Lambda functions in M2000 are value types. They have a list of closures, but closures are copies, except for those closures which are reference types. Lambdas can keep state in closures (they are mutable). But here we didn't do that. Y combinator is a lambda which return a lambda with a closure as f function. This function called passing as first argument itself by value. |
Lambda functions in M2000 are value types. They have a list of closures, but closures are copies, except for those closures which are reference types. Lambdas can keep state in closures (they are mutable). But here we didn't do that. Y combinator is a lambda which return a lambda with a closure as f function. This function called passing as first argument itself by value. |
||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module Ycombinator { |
Module Ycombinator { |
||
\\ y() return value. no use of closure |
\\ y() return value. no use of closure |
||
Line 3,849: | Line 3,849: | ||
} |
} |
||
Ycombinator |
Ycombinator |
||
</syntaxhighlight> |
|||
</lang> |
|||
<syntaxhighlight lang="m2000 interpreter"> |
|||
<lang M2000 Interpreter> |
|||
Module Checkit { |
Module Checkit { |
||
Rem { |
Rem { |
||
Line 3,886: | Line 3,886: | ||
} |
} |
||
CheckRecursion |
CheckRecursion |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|MANOOL}}== |
=={{header|MANOOL}}== |
||
Here one additional technique is demonstrated: the Y combinator is applied to a function ''during compilation'' due to the <code>$</code> operator, which is optional: |
Here one additional technique is demonstrated: the Y combinator is applied to a function ''during compilation'' due to the <code>$</code> operator, which is optional: |
||
<syntaxhighlight lang="manool"> |
|||
<lang MANOOL> |
|||
{ {extern "manool.org.18/std/0.3/all"} in |
{ {extern "manool.org.18/std/0.3/all"} in |
||
: let { Y = {proc {F} as {proc {X} as X[X]}[{proc {X} with {F} as F[{proc {Y} with {X} as X[X][Y]}]}]} } in |
: let { Y = {proc {F} as {proc {X} as X[X]}[{proc {X} with {F} as F[{proc {Y} with {X} as X[X][Y]}]}]} } in |
||
Line 3,902: | Line 3,902: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
Using less syntactic sugar: |
Using less syntactic sugar: |
||
<syntaxhighlight lang="manool"> |
|||
<lang MANOOL> |
|||
{ {extern "manool.org.18/std/0.3/all"} in |
{ {extern "manool.org.18/std/0.3/all"} in |
||
: let { Y = {proc {F} as {proc {X} as X[X]}[{proc {F; X} as F[{proc {X; Y} as X[X][Y]}.Bind[X]]}.Bind[F]]} } in |
: let { Y = {proc {F} as {proc {X} as X[X]}[{proc {F; X} as F[{proc {X; Y} as X[X][Y]}.Bind[X]]}.Bind[F]]} } in |
||
Line 3,916: | Line 3,916: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{output}} |
{{output}} |
||
<pre> |
<pre> |
||
Line 3,942: | Line 3,942: | ||
=={{header|Maple}}== |
=={{header|Maple}}== |
||
<syntaxhighlight lang="maple"> |
|||
<lang Maple> |
|||
> Y:=f->(x->x(x))(g->f((()->g(g)(args)))): |
> Y:=f->(x->x(x))(g->f((()->g(g)(args)))): |
||
> Yfac:=Y(f->(x->`if`(x<2,1,x*f(x-1)))): |
> Yfac:=Y(f->(x->`if`(x<2,1,x*f(x-1)))): |
||
Line 3,950: | Line 3,950: | ||
> seq( Yfib( i ), i = 1 .. 10 ); |
> seq( Yfib( i ), i = 1 .. 10 ); |
||
1, 1, 2, 3, 5, 8, 13, 21, 34, 55 |
1, 1, 2, 3, 5, 8, 13, 21, 34, 55 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
||
< |
<syntaxhighlight lang="mathematica">Y = Function[f, #[#] &[Function[g, f[g[g][##] &]]]]; |
||
factorial = Y[Function[f, If[# < 1, 1, # f[# - 1]] &]]; |
factorial = Y[Function[f, If[# < 1, 1, # f[# - 1]] &]]; |
||
fibonacci = Y[Function[f, If[# < 2, #, f[# - 1] + f[# - 2]] &]];</ |
fibonacci = Y[Function[f, If[# < 2, #, f[# - 1] + f[# - 2]] &]];</syntaxhighlight> |
||
=={{header|Moonscript}}== |
=={{header|Moonscript}}== |
||
< |
<syntaxhighlight lang="moonscript">Z = (f using nil) -> ((x) -> x x) (x) -> f (...) -> (x x) ... |
||
factorial = Z (f using nil) -> (n) -> if n == 0 then 1 else n * f n - 1</ |
factorial = Z (f using nil) -> (n) -> if n == 0 then 1 else n * f n - 1</syntaxhighlight> |
||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
< |
<syntaxhighlight lang="nim"># The following is implemented for a strict language as a Z-Combinator; |
||
# Z-combinators differ from Y-combinators in lacking one Beta reduction of |
# Z-combinators differ from Y-combinators in lacking one Beta reduction of |
||
# the extra `T` argument to the function to be recursed... |
# the extra `T` argument to the function to be recursed... |
||
Line 4,034: | Line 4,034: | ||
let fibs = fibsy |
let fibs = fibsy |
||
for _ in 1 .. 20: stdout.write fibs(), " " |
for _ in 1 .. 20: stdout.write fibs(), " " |
||
echo()</ |
echo()</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>3628800 |
<pre>3628800 |
||
Line 4,048: | Line 4,048: | ||
=={{header|Objective-C}}== |
=={{header|Objective-C}}== |
||
{{works with|Mac OS X|10.6+}}{{works with|iOS|4.0+}} |
{{works with|Mac OS X|10.6+}}{{works with|iOS|4.0+}} |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
typedef int (^Func)(int); |
typedef int (^Func)(int); |
||
Line 4,088: | Line 4,088: | ||
} |
} |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="objc">Func Y(FuncFunc f) { |
||
return ^(int x) { |
return ^(int x) { |
||
return f(Y(f))(x); |
return f(Y(f))(x); |
||
}; |
}; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
The Y-combinator over functions may be written directly in OCaml provided rectypes are enabled: |
The Y-combinator over functions may be written directly in OCaml provided rectypes are enabled: |
||
< |
<syntaxhighlight lang="ocaml">let fix f g = (fun x a -> f (x x) a) (fun x a -> f (x x) a) g</syntaxhighlight> |
||
Polymorphic variants are the simplest workaround in the absence of rectypes: |
Polymorphic variants are the simplest workaround in the absence of rectypes: |
||
< |
<syntaxhighlight lang="ocaml">let fix f = (fun (`X x) -> f(x (`X x))) (`X(fun (`X x) y -> f(x (`X x)) y));;</syntaxhighlight> |
||
Otherwise, an ordinary variant can be defined and used: |
Otherwise, an ordinary variant can be defined and used: |
||
< |
<syntaxhighlight lang="ocaml">type 'a mu = Roll of ('a mu -> 'a);; |
||
let unroll (Roll x) = x;; |
let unroll (Roll x) = x;; |
||
Line 4,129: | Line 4,129: | ||
fix fib 8;; |
fix fib 8;; |
||
(* - : int = 21 *)</ |
(* - : int = 21 *)</syntaxhighlight> |
||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="ocaml">let rec fix f x = f (fix f) x;;</syntaxhighlight> |
||
=={{header|Oforth}}== |
=={{header|Oforth}}== |
||
Line 4,138: | Line 4,138: | ||
With recursion into Y definition (so non stateless Y) : |
With recursion into Y definition (so non stateless Y) : |
||
< |
<syntaxhighlight lang="oforth">: Y(f) #[ f Y f perform ] ;</syntaxhighlight> |
||
Without recursion into Y definition (stateless Y). |
Without recursion into Y definition (stateless Y). |
||
< |
<syntaxhighlight lang="oforth">: X(me, f) #[ me f me perform f perform ] ; |
||
: Y(f) #X f X ;</ |
: Y(f) #X f X ;</syntaxhighlight> |
||
Usage : |
Usage : |
||
< |
<syntaxhighlight lang="oforth">: almost-fact(n, f) n ifZero: [ 1 ] else: [ n n 1 - f perform * ] ; |
||
#almost-fact Y => fact |
#almost-fact Y => fact |
||
Line 4,155: | Line 4,155: | ||
n 0 == ifTrue: [ 1 m 1 - f perform return ] |
n 0 == ifTrue: [ 1 m 1 - f perform return ] |
||
n 1 - m f perform m 1 - f perform ; |
n 1 - m f perform m 1 - f perform ; |
||
#almost-Ackermann Y => Ackermann </ |
#almost-Ackermann Y => Ackermann </syntaxhighlight> |
||
=={{header|Order}}== |
=={{header|Order}}== |
||
< |
<syntaxhighlight lang="c">#include <order/interpreter.h> |
||
#define ORDER_PP_DEF_8y \ |
#define ORDER_PP_DEF_8y \ |
||
Line 4,176: | Line 4,176: | ||
ORDER_PP(8to_lit(8ap(8y(8fac), 10))) // 3628800 |
ORDER_PP(8to_lit(8ap(8y(8fac), 10))) // 3628800 |
||
ORDER_PP(8ap(8y(8fib), 10)) // 55</ |
ORDER_PP(8ap(8y(8fib), 10)) // 55</syntaxhighlight> |
||
=={{header|Oz}}== |
=={{header|Oz}}== |
||
< |
<syntaxhighlight lang="oz">declare |
||
Y = fun {$ F} |
Y = fun {$ F} |
||
{fun {$ X} {X X} end |
{fun {$ X} {X X} end |
||
Line 4,201: | Line 4,201: | ||
in |
in |
||
{Show {Fac 5}} |
{Show {Fac 5}} |
||
{Show {Fib 8}}</ |
{Show {Fib 8}}</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
As of 2.8.0, GP cannot make general self-references in closures declared inline, so the Y combinator is required to implement these functions recursively in that environment, e.g., for use in parallel processing. |
As of 2.8.0, GP cannot make general self-references in closures declared inline, so the Y combinator is required to implement these functions recursively in that environment, e.g., for use in parallel processing. |
||
< |
<syntaxhighlight lang="parigp">Y(f)=x->f(f,x); |
||
fact=Y((f,n)->if(n,n*f(f,n-1),1)); |
fact=Y((f,n)->if(n,n*f(f,n-1),1)); |
||
fib=Y((f,n)->if(n>1,f(f,n-1)+f(f,n-2),n)); |
fib=Y((f,n)->if(n>1,f(f,n-1)+f(f,n-2),n)); |
||
apply(fact, [1..10]) |
apply(fact, [1..10]) |
||
apply(fib, [1..10])</ |
apply(fib, [1..10])</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>%1 = [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800] |
<pre>%1 = [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800] |
||
Line 4,215: | Line 4,215: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
< |
<syntaxhighlight lang="perl">sub Y { my $f = shift; # λf. |
||
sub { my $x = shift; $x->($x) }->( # (λx.x x) |
sub { my $x = shift; $x->($x) }->( # (λx.x x) |
||
sub {my $y = shift; $f->(sub {$y->($y)(@_)})} # λy.f λz.y y z |
sub {my $y = shift; $f->(sub {$y->($y)(@_)})} # λy.f λz.y y z |
||
Line 4,228: | Line 4,228: | ||
for my $f ($fac, $fib) { |
for my $f ($fac, $fib) { |
||
print join(' ', map Y($f)->($_), 0..9), "\n"; |
print join(' ', map Y($f)->($_), 0..9), "\n"; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>1 1 2 6 24 120 720 5040 40320 362880 |
<pre>1 1 2 6 24 120 720 5040 40320 362880 |
||
Line 4,234: | Line 4,234: | ||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="perl">sub Y { my $f = shift; |
||
sub {$f->(Y($f))->(@_)} |
sub {$f->(Y($f))->(@_)} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Line 4,249: | Line 4,249: | ||
[[Partial_function_application#Phix|Partial_function_application]], |
[[Partial_function_application#Phix|Partial_function_application]], |
||
and/or [[Function_composition#Phix|Function_composition]] |
and/or [[Function_composition#Phix|Function_composition]] |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
<span style="color: #008080;">function</span> <span style="color: #000000;">call_fn</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> |
<span style="color: #008080;">function</span> <span style="color: #000000;">call_fn</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> |
||
Line 4,277: | Line 4,277: | ||
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"fac"</span><span style="color: #0000FF;">)</span> |
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"fac"</span><span style="color: #0000FF;">)</span> |
||
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"fib"</span><span style="color: #0000FF;">)</span> |
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"fib"</span><span style="color: #0000FF;">)</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 4,285: | Line 4,285: | ||
=={{header|Phixmonti}}== |
=={{header|Phixmonti}}== |
||
< |
<syntaxhighlight lang="phixmonti">0 var subr |
||
def fac |
def fac |
||
Line 4,309: | Line 4,309: | ||
getid fac "fac" test |
getid fac "fac" test |
||
getid fib "fib" test</ |
getid fib "fib" test</syntaxhighlight> |
||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
{{works with|PHP|5.3+}} |
{{works with|PHP|5.3+}} |
||
< |
<syntaxhighlight lang="php"><?php |
||
function Y($f) { |
function Y($f) { |
||
$g = function($w) use($f) { |
$g = function($w) use($f) { |
||
Line 4,334: | Line 4,334: | ||
echo $factorial(10), "\n"; |
echo $factorial(10), "\n"; |
||
?></ |
?></syntaxhighlight> |
||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="php">function Y($f) { |
||
return function() use($f) { |
return function() use($f) { |
||
return call_user_func_array($f(Y($f)), func_get_args()); |
return call_user_func_array($f(Y($f)), func_get_args()); |
||
}; |
}; |
||
}</ |
}</syntaxhighlight> |
||
{{works with|PHP|pre-5.3 and 5.3+}} |
{{works with|PHP|pre-5.3 and 5.3+}} |
||
with <tt>create_function</tt> instead of real closures. A little far-fetched, but... |
with <tt>create_function</tt> instead of real closures. A little far-fetched, but... |
||
< |
<syntaxhighlight lang="php"><?php |
||
function Y($f) { |
function Y($f) { |
||
$g = create_function('$w', '$f = '.var_export($f,true).'; |
$g = create_function('$w', '$f = '.var_export($f,true).'; |
||
Line 4,369: | Line 4,369: | ||
$factorial = Y('almost_fac'); |
$factorial = Y('almost_fac'); |
||
echo $factorial(10), "\n"; |
echo $factorial(10), "\n"; |
||
?></ |
?></syntaxhighlight> |
||
A functionally equivalent version using the <code>$this</code> parameter in closures is also possible: |
A functionally equivalent version using the <code>$this</code> parameter in closures is also possible: |
||
{{works with|PHP|5.4+}} |
{{works with|PHP|5.4+}} |
||
< |
<syntaxhighlight lang="php"><?php |
||
function pseudoY($f) { |
function pseudoY($f) { |
||
$g = function($w) use ($f) { |
$g = function($w) use ($f) { |
||
Line 4,392: | Line 4,392: | ||
}); |
}); |
||
echo $fibonacci(10), "\n"; |
echo $fibonacci(10), "\n"; |
||
?></ |
?></syntaxhighlight> |
||
However, <code>pseudoY()</code> is not a fixed-point combinator. |
However, <code>pseudoY()</code> is not a fixed-point combinator. |
||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
{{trans|Common Lisp}} |
{{trans|Common Lisp}} |
||
< |
<syntaxhighlight lang="picolisp">(de Y (F) |
||
(let X (curry (F) (Y) (F (curry (Y) @ (pass (Y Y))))) |
(let X (curry (F) (Y) (F (curry (Y) @ (pass (Y Y))))) |
||
(X X) ) )</ |
(X X) ) )</syntaxhighlight> |
||
===Factorial=== |
===Factorial=== |
||
< |
<syntaxhighlight lang="picolisp"># Factorial |
||
(de fact (F) |
(de fact (F) |
||
(curry (F) (N) |
(curry (F) (N) |
||
Line 4,409: | Line 4,409: | ||
: ((Y fact) 6) |
: ((Y fact) 6) |
||
-> 720</ |
-> 720</syntaxhighlight> |
||
===Fibonacci sequence=== |
===Fibonacci sequence=== |
||
< |
<syntaxhighlight lang="picolisp"># Fibonacci |
||
(de fibo (F) |
(de fibo (F) |
||
(curry (F) (N) |
(curry (F) (N) |
||
Line 4,420: | Line 4,420: | ||
: ((Y fibo) 22) |
: ((Y fibo) 22) |
||
-> 28657</ |
-> 28657</syntaxhighlight> |
||
===Ackermann function=== |
===Ackermann function=== |
||
< |
<syntaxhighlight lang="picolisp"># Ackermann |
||
(de ack (F) |
(de ack (F) |
||
(curry (F) (X Y) |
(curry (F) (X Y) |
||
Line 4,432: | Line 4,432: | ||
: ((Y ack) 3 4) |
: ((Y ack) 3 4) |
||
-> 125</ |
-> 125</syntaxhighlight> |
||
=={{header|Pop11}}== |
=={{header|Pop11}}== |
||
< |
<syntaxhighlight lang="pop11">define Y(f); |
||
procedure (x); x(x) endprocedure( |
procedure (x); x(x) endprocedure( |
||
procedure (y); |
procedure (y); |
||
Line 4,456: | Line 4,456: | ||
Y(fac)(5) => |
Y(fac)(5) => |
||
Y(fib)(5) =></ |
Y(fib)(5) =></syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 4,466: | Line 4,466: | ||
{{trans|Joy}} |
{{trans|Joy}} |
||
{{libheader|initlib}} |
{{libheader|initlib}} |
||
< |
<syntaxhighlight lang="postscript">y { |
||
{dup cons} exch concat dup cons i |
{dup cons} exch concat dup cons i |
||
}. |
}. |
||
Line 4,473: | Line 4,473: | ||
{ {pop zero?} {pop succ} {{dup pred} dip i *} ifte } |
{ {pop zero?} {pop succ} {{dup pred} dip i *} ifte } |
||
y |
y |
||
}.</ |
}.</syntaxhighlight> |
||
=={{header|PowerShell}}== |
=={{header|PowerShell}}== |
||
Line 4,484: | Line 4,484: | ||
Z & := & \lambda f.(\lambda x.f\ (\lambda y.x\ x\ y))\ (\lambda x.f\ (\lambda y.x\ x\ y)) \\ |
Z & := & \lambda f.(\lambda x.f\ (\lambda y.x\ x\ y))\ (\lambda x.f\ (\lambda y.x\ x\ y)) \\ |
||
\end{array}</math> |
\end{array}</math> |
||
< |
<syntaxhighlight lang="powershell">$fac = { |
||
param([ScriptBlock] $f) |
param([ScriptBlock] $f) |
||
invoke-expression @" |
invoke-expression @" |
||
Line 4,534: | Line 4,534: | ||
$Z.InvokeReturnAsIs($fac).InvokeReturnAsIs(5) |
$Z.InvokeReturnAsIs($fac).InvokeReturnAsIs(5) |
||
$Z.InvokeReturnAsIs($fib).InvokeReturnAsIs(5)</ |
$Z.InvokeReturnAsIs($fib).InvokeReturnAsIs(5)</syntaxhighlight> |
||
GetNewClosure() was added in Powershell 2, allowing for an implementation without metaprogramming. The following was tested with Powershell 4. |
GetNewClosure() was added in Powershell 2, allowing for an implementation without metaprogramming. The following was tested with Powershell 4. |
||
< |
<syntaxhighlight lang="powershell">$Y = { |
||
param ($f) |
param ($f) |
||
Line 4,586: | Line 4,586: | ||
$Y.invoke($fact).invoke(5) |
$Y.invoke($fact).invoke(5) |
||
$Y.invoke($fib).invoke(5)</ |
$Y.invoke($fib).invoke(5)</syntaxhighlight> |
||
=={{header|Prolog}}== |
=={{header|Prolog}}== |
||
Line 4,593: | Line 4,593: | ||
The code is inspired from this page : http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord#Hiord (p 106). <br> |
The code is inspired from this page : http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/ISO-Hiord#Hiord (p 106). <br> |
||
Original code is from <b>Hermenegildo</b> and al : <b>Hiord: A Type-Free Higher-Order Logic Programming Language with Predicate Abstraction</b>, pdf accessible here http://www.stups.uni-duesseldorf.de/asap/?id=129. |
Original code is from <b>Hermenegildo</b> and al : <b>Hiord: A Type-Free Higher-Order Logic Programming Language with Predicate Abstraction</b>, pdf accessible here http://www.stups.uni-duesseldorf.de/asap/?id=129. |
||
< |
<syntaxhighlight lang="prolog">:- use_module(lambda). |
||
% The Y combinator |
% The Y combinator |
||
Line 4,624: | Line 4,624: | ||
), |
), |
||
y(Fact, 10, FF), format('Fact(~w) = ~w~n', [10, FF]).</ |
y(Fact, 10, FF), format('Fact(~w) = ~w~n', [10, FF]).</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 4,633: | Line 4,633: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="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)) |
>>> fac = lambda f: lambda n: (1 if n<2 else n*f(n-1)) |
||
>>> [ Y(fac)(i) for i in range(10) ] |
>>> [ Y(fac)(i) for i in range(10) ] |
||
Line 4,639: | Line 4,639: | ||
>>> fib = lambda f: lambda n: 0 if n == 0 else (1 if n == 1 else f(n-1) + f(n-2)) |
>>> 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) ] |
>>> [ Y(fib)(i) for i in range(10) ] |
||
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]</ |
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]</syntaxhighlight> |
||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="python">Y = lambda f: lambda *args: f(Y(f))(*args)</syntaxhighlight> |
||
< |
<syntaxhighlight lang="python">Y = lambda b: ((lambda f: b(lambda *x: f(f)(*x)))((lambda f: b(lambda *x: f(f)(*x)))))</syntaxhighlight> |
||
=={{header|Q}}== |
=={{header|Q}}== |
||
< |
<syntaxhighlight lang="q">> Y: {{x x} {({y {(x x) y} x} y) x} x} |
||
> fac: {{$[y<2; 1; y*x y-1]} x} |
> fac: {{$[y<2; 1; y*x y-1]} x} |
||
> (Y fac) 6 |
> (Y fac) 6 |
||
Line 4,654: | Line 4,654: | ||
> (Y fib) each til 20 |
> (Y fib) each til 20 |
||
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 |
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Quackery}}== |
=={{header|Quackery}}== |
||
Line 4,668: | Line 4,668: | ||
Without the restriction on self referencing, <code>recursive</code> could be defined as <code>[ ' [ this ] swap nested join ]</code>. |
Without the restriction on self referencing, <code>recursive</code> could be defined as <code>[ ' [ this ] swap nested join ]</code>. |
||
< |
<syntaxhighlight lang="quackery"> [ ' stack nested nested |
||
' share nested join |
' share nested join |
||
swap nested join |
swap nested join |
||
Line 4,682: | Line 4,682: | ||
say "8 factorial = " 8 ' factorial recursive do echo cr |
say "8 factorial = " 8 ' factorial recursive do echo cr |
||
say "8 fibonacci = " 8 ' fibonacci recursive do echo cr</ |
say "8 fibonacci = " 8 ' fibonacci recursive do echo cr</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 4,691: | Line 4,691: | ||
=={{header|R}}== |
=={{header|R}}== |
||
< |
<syntaxhighlight lang="r">Y <- function(f) { |
||
(function(x) { (x)(x) })( function(y) { f( (function(a) {y(y)})(a) ) } ) |
(function(x) { (x)(x) })( function(y) { f( (function(a) {y(y)})(a) ) } ) |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="r">fac <- function(f) { |
||
function(n) { |
function(n) { |
||
if (n<2) |
if (n<2) |
||
Line 4,711: | Line 4,711: | ||
f(n-1) + f(n-2) |
f(n-1) + f(n-2) |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="r">for(i in 1:9) print(Y(fac)(i)) |
||
for(i in 1:9) print(Y(fib)(i))</ |
for(i in 1:9) print(Y(fib)(i))</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
The lazy implementation |
The lazy implementation |
||
< |
<syntaxhighlight lang="racket">#lang lazy |
||
(define Y (λ (f) ((λ (x) (f (x x))) (λ (x) (f (x x)))))) |
(define Y (λ (f) ((λ (x) (f (x x))) (λ (x) (f (x x)))))) |
||
Line 4,726: | Line 4,726: | ||
(Y (λ (fact) (λ (n) (if (zero? n) 1 (* n (fact (- n 1)))))))) |
(Y (λ (fact) (λ (n) (if (zero? n) 1 (* n (fact (- n 1)))))))) |
||
(define Fib |
(define Fib |
||
(Y (λ (fib) (λ (n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))))))</ |
(Y (λ (fib) (λ (n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))))))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 4,737: | Line 4,737: | ||
Strict realization: |
Strict realization: |
||
< |
<syntaxhighlight lang="racket">#lang racket |
||
(define Y (λ (b) ((λ (f) (b (λ (x) ((f f) x)))) |
(define Y (λ (b) ((λ (f) (b (λ (x) ((f f) x)))) |
||
(λ (f) (b (λ (x) ((f f) x)))))))</ |
(λ (f) (b (λ (x) ((f f) x)))))))</syntaxhighlight> |
||
Definitions of <tt>Fact</tt> and <tt>Fib</tt> functions will be the same as in Lazy Racket. |
Definitions of <tt>Fact</tt> and <tt>Fib</tt> 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: |
Finally, a definition in Typed Racket is a little difficult as in other statically typed languages: |
||
< |
<syntaxhighlight lang="racket">#lang typed/racket |
||
(: make-recursive : (All (S T) ((S -> T) -> (S -> T)) -> (S -> T))) |
(: make-recursive : (All (S T) ((S -> T) -> (S -> T)) -> (S -> T))) |
||
Line 4,760: | Line 4,760: | ||
(* n (fact (- n 1)))))))) |
(* n (fact (- n 1)))))))) |
||
(fact 5)</ |
(fact 5)</syntaxhighlight> |
||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(formerly Perl 6) |
||
<lang |
<syntaxhighlight lang="raku" line>sub Y (&f) { sub (&x) { x(&x) }( sub (&y) { f(sub ($x) { y(&y)($x) }) } ) } |
||
sub fac (&f) { sub ($n) { $n < 2 ?? 1 !! $n * f($n - 1) } } |
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) } } |
sub fib (&f) { sub ($n) { $n < 2 ?? $n !! f($n - 1) + f($n - 2) } } |
||
say map Y($_), ^10 for &fac, &fib;</ |
say map Y($_), ^10 for &fac, &fib;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>(1 1 2 6 24 120 720 5040 40320 362880) |
<pre>(1 1 2 6 24 120 720 5040 40320 362880) |
||
Line 4,774: | Line 4,774: | ||
Note that Raku doesn't actually need a Y combinator because you can name anonymous functions from the inside: |
Note that Raku doesn't actually need a Y combinator because you can name anonymous functions from the inside: |
||
<lang |
<syntaxhighlight lang="raku" line>say .(10) given sub (Int $x) { $x < 2 ?? 1 !! $x * &?ROUTINE($x - 1); }</syntaxhighlight> |
||
=={{header|REBOL}}== |
=={{header|REBOL}}== |
||
< |
<syntaxhighlight lang="rebol">Y: closure [g] [do func [f] [f :f] closure [f] [g func [x] [do f :f :x]]]</syntaxhighlight> |
||
;usage example |
;usage example |
||
< |
<syntaxhighlight lang="rebol">fact*: closure [h] [func [n] [either n <= 1 [1] [n * h n - 1]]] |
||
fact: Y :fact*</ |
fact: Y :fact*</syntaxhighlight> |
||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
Programming note: '''length''', '''reverse''', '''sign''', '''trunc''', '''b2x''', '''d2x''', and '''x2d''' are REXX BIFs ('''B'''uilt '''I'''n '''F'''unctions). |
Programming note: '''length''', '''reverse''', '''sign''', '''trunc''', '''b2x''', '''d2x''', and '''x2d''' are REXX BIFs ('''B'''uilt '''I'''n '''F'''unctions). |
||
< |
<syntaxhighlight lang="rexx">/*REXX program implements and displays a stateless Y combinator. */ |
||
numeric digits 1000 /*allow big numbers. */ |
numeric digits 1000 /*allow big numbers. */ |
||
say ' fib' Y(fib (50) ) /*Fibonacci series. */ |
say ' fib' Y(fib (50) ) /*Fibonacci series. */ |
||
Line 4,810: | Line 4,810: | ||
tfact: procedure; parse arg x; != 1; do j=x to 2 by -3; != !*j; end; return ! |
tfact: procedure; parse arg x; != 1; do j=x to 2 by -3; != !*j; end; return ! |
||
qfact: procedure; parse arg x; != 1; do j=x to 2 by -4; != !*j; end; return ! |
qfact: procedure; parse arg x; != 1; do j=x to 2 by -4; != !*j; end; return ! |
||
fact: procedure; parse arg x; != 1; do j=2 to x ; != !*j; end; return !</ |
fact: procedure; parse arg x; != 1; do j=2 to x ; != !*j; end; return !</syntaxhighlight> |
||
{{out|output|text= when using the internal default input:}} |
{{out|output|text= when using the internal default input:}} |
||
<pre> |
<pre> |
||
Line 4,832: | Line 4,832: | ||
Using a lambda: |
Using a lambda: |
||
< |
<syntaxhighlight lang="ruby">y = lambda do |f| |
||
lambda {|g| g[g]}[lambda do |g| |
lambda {|g| g[g]}[lambda do |g| |
||
f[lambda {|*args| g[g][*args]}] |
f[lambda {|*args| g[g][*args]}] |
||
Line 4,842: | Line 4,842: | ||
fib = lambda{|f| lambda{|n| n < 2 ? n : f[n-1] + f[n-2]}} |
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]</ |
p Array.new(10) {|i| y[fib][i]} #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]</syntaxhighlight> |
||
Same as the above, using the new short lambda syntax: |
Same as the above, using the new short lambda syntax: |
||
{{works with|Ruby|1.9}} |
{{works with|Ruby|1.9}} |
||
< |
<syntaxhighlight lang="ruby">y = ->(f) {->(g) {g.(g)}.(->(g) { f.(->(*args) {g.(g).(*args)})})} |
||
fac = ->(f) { ->(n) { n < 2 ? 1 : n * f.(n-1) } } |
fac = ->(f) { ->(n) { n < 2 ? 1 : n * f.(n-1) } } |
||
Line 4,854: | Line 4,854: | ||
fib = ->(f) { ->(n) { n < 2 ? n : f.(n-2) + f.(n-1) } } |
fib = ->(f) { ->(n) { n < 2 ? n : f.(n-2) + f.(n-1) } } |
||
p 10.times.map {|i| y.(fib).(i)}</ |
p 10.times.map {|i| y.(fib).(i)}</syntaxhighlight> |
||
Using a method: |
Using a method: |
||
{{works with|Ruby|1.9}} |
{{works with|Ruby|1.9}} |
||
< |
<syntaxhighlight lang="ruby">def y(&f) |
||
lambda do |g| |
lambda do |g| |
||
f.call {|*args| g[g][*args]} |
f.call {|*args| g[g][*args]} |
||
Line 4,871: | Line 4,871: | ||
# => [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880] |
# => [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880] |
||
p Array.new(10) {|i| fib[i]} |
p Array.new(10) {|i| fib[i]} |
||
# => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]</ |
# => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]</syntaxhighlight> |
||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="ruby">y = lambda do |f| |
||
lambda {|*args| f[y[f]][*args]} |
lambda {|*args| f[y[f]][*args]} |
||
end</ |
end</syntaxhighlight> |
||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
{{works with|Rust|1.44.1 stable}} |
{{works with|Rust|1.44.1 stable}} |
||
< |
<syntaxhighlight lang="rust"> |
||
//! A simple implementation of the Y Combinator: |
//! A simple implementation of the Y Combinator: |
||
//! λf.(λx.xx)(λx.f(xx)) |
//! λf.(λx.xx)(λx.f(xx)) |
||
Line 4,936: | Line 4,936: | ||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{output}} |
{{output}} |
||
<pre> |
<pre> |
||
Line 4,945: | Line 4,945: | ||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
Credit goes to the thread in [https://web.archive.org/web/20160709050901/http://scala-blogs.org/2008/09/y-combinator-in-scala.html scala blog] |
Credit goes to the thread in [https://web.archive.org/web/20160709050901/http://scala-blogs.org/2008/09/y-combinator-in-scala.html scala blog] |
||
< |
<syntaxhighlight lang="scala"> |
||
def Y[A, B](f: (A => B) => (A => B)): A => B = { |
def Y[A, B](f: (A => B) => (A => B)): A => B = { |
||
case class W(wf: W => (A => B)) { |
case class W(wf: W => (A => B)) { |
||
Line 4,953: | Line 4,953: | ||
g(W(g)) |
g(W(g)) |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
Example |
Example |
||
< |
<syntaxhighlight lang="scala"> |
||
val fac: Int => Int = Y[Int, Int](f => i => if (i <= 0) 1 else f(i - 1) * i) |
val fac: Int => Int = Y[Int, Int](f => i => if (i <= 0) 1 else f(i - 1) * i) |
||
fac(6) //> res0: Int = 720 |
fac(6) //> res0: Int = 720 |
||
Line 4,961: | Line 4,961: | ||
val fib: Int => Int = Y[Int, Int](f => i => if (i < 2) i else f(i - 1) + f(i - 2)) |
val fib: Int => Int = Y[Int, Int](f => i => if (i < 2) i else f(i - 1) + f(i - 2)) |
||
fib(6) //> res1: Int = 8 |
fib(6) //> res1: Int = 8 |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Scheme}}== |
=={{header|Scheme}}== |
||
< |
<syntaxhighlight lang="scheme">(define Y ; (Y f) = (g g) where |
||
(lambda (f) ; (g g) = (f (lambda a (apply (g g) a))) |
(lambda (f) ; (g g) = (f (lambda a (apply (g g) a))) |
||
((lambda (g) (g g)) ; (Y f) == (f (lambda a (apply (Y f) a))) |
((lambda (g) (g g)) ; (Y f) == (f (lambda a (apply (Y f) a))) |
||
Line 5,010: | Line 5,010: | ||
(display (fib2 134)) |
(display (fib2 134)) |
||
(newline)</ |
(newline)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>720 |
<pre>720 |
||
Line 5,017: | Line 5,017: | ||
If we were allowed to use recursion (with <code>Y</code> referring to itself by name in its body) we could define the equivalent to the above as |
If we were allowed to use recursion (with <code>Y</code> referring to itself by name in its body) we could define the equivalent to the above as |
||
< |
<syntaxhighlight lang="scheme">(define Yr ; (Y f) == (f (lambda a (apply (Y f) a))) |
||
(lambda (f) |
(lambda (f) |
||
(f (lambda a (apply (Yr f) a)))))</ |
(f (lambda a (apply (Yr f) a)))))</syntaxhighlight> |
||
And another way is: |
And another way is: |
||
< |
<syntaxhighlight lang="scheme">(define Y2r |
||
(lambda (f) |
(lambda (f) |
||
(lambda a (apply (f (Y2r f)) a))))</ |
(lambda a (apply (f (Y2r f)) a))))</syntaxhighlight> |
||
Which, non-recursively, is |
Which, non-recursively, is |
||
< |
<syntaxhighlight lang="scheme">(define Y2 ; (Y2 f) = (g g) where |
||
(lambda (f) ; (g g) = (lambda a (apply (f (g g)) a)) |
(lambda (f) ; (g g) = (lambda a (apply (f (g g)) a)) |
||
((lambda (g) (g g)) ; (Y2 f) == (lambda a (apply (f (Y2 f)) a)) |
((lambda (g) (g g)) ; (Y2 f) == (lambda a (apply (f (Y2 f)) a)) |
||
(lambda (g) |
(lambda (g) |
||
(lambda a (apply (f (g g)) a))))))</ |
(lambda a (apply (f (g g)) a))))))</syntaxhighlight> |
||
=={{header|Shen}}== |
=={{header|Shen}}== |
||
< |
<syntaxhighlight lang="shen">(define y |
||
F -> ((/. X (X X)) |
F -> ((/. X (X X)) |
||
(/. X (F (/. Z ((X X) Z)))))) |
(/. X (F (/. Z ((X X) Z)))))) |
||
Line 5,044: | Line 5,044: | ||
(Fac 0) |
(Fac 0) |
||
(Fac 5) |
(Fac 5) |
||
(Fac 10)))</ |
(Fac 10)))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>1 |
<pre>1 |
||
Line 5,051: | Line 5,051: | ||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
< |
<syntaxhighlight lang="ruby">var y = ->(f) {->(g) {g(g)}(->(g) { f(->(*args) {g(g)(args...)})})} |
||
var fac = ->(f) { ->(n) { n < 2 ? 1 : (n * f(n-1)) } } |
var fac = ->(f) { ->(n) { n < 2 ? 1 : (n * f(n-1)) } } |
||
Line 5,057: | Line 5,057: | ||
var fib = ->(f) { ->(n) { n < 2 ? n : (f(n-2) + f(n-1)) } } |
var fib = ->(f) { ->(n) { n < 2 ? n : (f(n-2) + f(n-1)) } } |
||
say 10.of { |i| y(fib)(i) }</ |
say 10.of { |i| y(fib)(i) }</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 5,066: | Line 5,066: | ||
=={{header|Slate}}== |
=={{header|Slate}}== |
||
The Y combinator is already defined in slate as: |
The Y combinator is already defined in slate as: |
||
< |
<syntaxhighlight lang="slate">Method traits define: #Y &builder: |
||
[[| :f | [| :x | f applyWith: (x applyWith: x)] |
[[| :f | [| :x | f applyWith: (x applyWith: x)] |
||
applyWith: [| :x | f applyWith: (x applyWith: x)]]].</ |
applyWith: [| :x | f applyWith: (x applyWith: x)]]].</syntaxhighlight> |
||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
||
{{works with|GNU Smalltalk}} |
{{works with|GNU Smalltalk}} |
||
< |
<syntaxhighlight lang="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 := Y value: [:f| [:i| i <= 1 ifTrue: [i] ifFalse: [(f value: i-1) + (f value: i-2)] ] ]. |
||
Line 5,080: | Line 5,080: | ||
fact := Y value: [:f| [:i| i = 0 ifTrue: [1] ifFalse: [(f value: i-1) * i] ] ]. |
fact := Y value: [:f| [:i| i = 0 ifTrue: [1] ifFalse: [(f value: i-1) * i] ] ]. |
||
(fact value: 10) displayNl.</ |
(fact value: 10) displayNl.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>55 |
<pre>55 |
||
Line 5,086: | Line 5,086: | ||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="smalltalk">Y := [:f| [:x| (f value: (Y value: f)) value: x] ].</syntaxhighlight> |
||
=={{header|Standard ML}}== |
=={{header|Standard ML}}== |
||
< |
<syntaxhighlight lang="sml">- datatype 'a mu = Roll of ('a mu -> 'a) |
||
fun unroll (Roll x) = x |
fun unroll (Roll x) = x |
||
Line 5,109: | Line 5,109: | ||
val it = [1,1,2,6,24,120,720,5040,40320,362880] : int list |
val it = [1,1,2,6,24,120,720,5040,40320,362880] : int list |
||
- List.tabulate (10, fix fib); |
- List.tabulate (10, fix fib); |
||
val it = [0,1,1,2,3,5,8,13,21,34] : int list</ |
val it = [0,1,1,2,3,5,8,13,21,34] : int list</syntaxhighlight> |
||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="sml">fun fix f x = f (fix f) x</syntaxhighlight> |
||
=={{header|SuperCollider}}== |
=={{header|SuperCollider}}== |
||
Like Ruby, SuperCollider needs an extra level of lambda-abstraction to implement the y-combinator. The z-combinator is straightforward: |
Like Ruby, SuperCollider needs an extra level of lambda-abstraction to implement the y-combinator. The z-combinator is straightforward: |
||
< |
<syntaxhighlight lang="supercollider">// z-combinator |
||
( |
( |
||
z = { |f| |
z = { |f| |
||
Line 5,157: | Line 5,157: | ||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Swift}}== |
=={{header|Swift}}== |
||
Using a recursive type: |
Using a recursive type: |
||
< |
<syntaxhighlight lang="swift">struct RecursiveFunc<F> { |
||
let o : RecursiveFunc<F> -> F |
let o : RecursiveFunc<F> -> F |
||
} |
} |
||
Line 5,177: | Line 5,177: | ||
} |
} |
||
println("fac(5) = \(fac(5))") |
println("fac(5) = \(fac(5))") |
||
println("fib(9) = \(fib(9))")</ |
println("fib(9) = \(fib(9))")</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 5,186: | Line 5,186: | ||
Without a recursive type, and instead using <code>Any</code> to erase the type: |
Without a recursive type, and instead using <code>Any</code> to erase the type: |
||
{{works with|Swift|1.2+}} (for Swift 1.1 replace <code>as!</code> with <code>as</code>) |
{{works with|Swift|1.2+}} (for Swift 1.1 replace <code>as!</code> with <code>as</code>) |
||
< |
<syntaxhighlight lang="swift">func Y<A, B>(f: (A -> B) -> A -> B) -> A -> B { |
||
typealias RecursiveFunc = Any -> A -> B |
typealias RecursiveFunc = Any -> A -> B |
||
let r : RecursiveFunc = { (z: Any) in let w = z as! RecursiveFunc; return f { w(w)($0) } } |
let r : RecursiveFunc = { (z: Any) in let w = z as! RecursiveFunc; return f { w(w)($0) } } |
||
return r(r) |
return r(r) |
||
}</ |
}</syntaxhighlight> |
||
The usual version using recursion, disallowed by the task: |
The usual version using recursion, disallowed by the task: |
||
< |
<syntaxhighlight lang="swift">func Y<In, Out>( f: (In->Out) -> (In->Out) ) -> (In->Out) { |
||
return { x in f(Y(f))(x) } |
return { x in f(Y(f))(x) } |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Tailspin}}== |
=={{header|Tailspin}}== |
||
< |
<syntaxhighlight lang="tailspin"> |
||
// YCombinator is not needed since tailspin supports recursion readily, but this demonstrates passing functions as parameters |
// YCombinator is not needed since tailspin supports recursion readily, but this demonstrates passing functions as parameters |
||
Line 5,231: | Line 5,231: | ||
5 -> fibonacci -> 'fibonacci 5: $; |
5 -> fibonacci -> 'fibonacci 5: $; |
||
' -> !OUT::write |
' -> !OUT::write |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 5,244: | Line 5,244: | ||
This prints out 24, the factorial of 4: |
This prints out 24, the factorial of 4: |
||
< |
<syntaxhighlight lang="txrlisp">;; The Y combinator: |
||
(defun y (f) |
(defun y (f) |
||
[(op @1 @1) |
[(op @1 @1) |
||
Line 5,256: | Line 5,256: | ||
;; Test: |
;; Test: |
||
(format t "~s\n" [[y fac] 4])</ |
(format t "~s\n" [[y fac] 4])</syntaxhighlight> |
||
Both the <code>op</code> and <code>do</code> operators are a syntactic sugar for currying, in two different flavors. The forms within <code>do</code> that are symbols are evaluated in the normal Lisp-2 style and the first symbol can be an operator. Under <code>op</code>, 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 <code>do</code> stems from the fact that the operator is used for currying over special forms like <code>if</code> in the above example, where there is evaluation control. Operators can have side effects: they can "do" something. Consider <code>(do set a @1)</code> which yields a function of one argument which assigns that argument to <code>a</code>. |
Both the <code>op</code> and <code>do</code> operators are a syntactic sugar for currying, in two different flavors. The forms within <code>do</code> that are symbols are evaluated in the normal Lisp-2 style and the first symbol can be an operator. Under <code>op</code>, 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 <code>do</code> stems from the fact that the operator is used for currying over special forms like <code>if</code> in the above example, where there is evaluation control. Operators can have side effects: they can "do" something. Consider <code>(do set a @1)</code> which yields a function of one argument which assigns that argument to <code>a</code>. |
||
The compounded <code>@@...</code> notation allows for inner functions to refer to outer parameters, when the notation is nested. Consider < |
The compounded <code>@@...</code> notation allows for inner functions to refer to outer parameters, when the notation is nested. Consider <syntaxhighlight lang="txrlisp">(op foo @1 (op bar @2 @@2))</syntaxhighlight>. Here the <code>@2</code> refers to the second argument of the anonymous function denoted by the inner <code>op</code>. The <code>@@2</code> refers to the second argument of the outer <code>op</code>. |
||
=={{header|Ursala}}== |
=={{header|Ursala}}== |
||
The standard y combinator doesn't work in Ursala due to eager |
The standard y combinator doesn't work in Ursala due to eager |
||
evaluation, but an alternative is easily defined as shown |
evaluation, but an alternative is easily defined as shown |
||
< |
<syntaxhighlight lang="ursala">(r "f") "x" = "f"("f","x") |
||
my_fix "h" = r ("f","x"). ("h" r "f") "x"</ |
my_fix "h" = r ("f","x"). ("h" r "f") "x"</syntaxhighlight> |
||
or by this shorter expression for the same thing in point free form. |
or by this shorter expression for the same thing in point free form. |
||
< |
<syntaxhighlight lang="ursala">my_fix = //~&R+ ^|H\~&+ ; //~&R</syntaxhighlight> |
||
Normally you'd like to define a function recursively by writing |
Normally you'd like to define a function recursively by writing |
||
<math>f = h(f)</math>, where <math>h(f)</math> is just the body of the |
<math>f = h(f)</math>, where <math>h(f)</math> is just the body of the |
||
Line 5,276: | Line 5,276: | ||
quotes signify a dummy variable. Using this |
quotes signify a dummy variable. Using this |
||
method, the definition of the factorial function becomes |
method, the definition of the factorial function becomes |
||
< |
<syntaxhighlight lang="ursala">#import nat |
||
fact = my_fix "f". ~&?\1! product^/~& "f"+ predecessor</ |
fact = my_fix "f". ~&?\1! product^/~& "f"+ predecessor</syntaxhighlight> |
||
To make it easier, the compiler has a directive to let you install |
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 |
your own fixed point combinator for it to use, which looks like |
||
this, |
this, |
||
<lang |
<syntaxhighlight lang="ursala">#fix my_fix</syntaxhighlight> |
||
with your choice of function to be used in place of <code>my_fix</code>. |
with your choice of function to be used in place of <code>my_fix</code>. |
||
Having done that, you may express recursive functions per convention by circular definitions, |
Having done that, you may express recursive functions per convention by circular definitions, |
||
as in this example of a Fibonacci function. |
as in this example of a Fibonacci function. |
||
< |
<syntaxhighlight lang="ursala">fib = {0,1}?</1! sum+ fib~~+ predecessor^~/~& predecessor</syntaxhighlight> |
||
Note that this way is only syntactic sugar for the for explicit way |
Note that this way is only syntactic sugar for the for explicit way |
||
shown above. Without a fixed point combinator given in the <code>#fix</code> |
shown above. Without a fixed point combinator given in the <code>#fix</code> |
||
Line 5,295: | Line 5,295: | ||
To confirm that all this works, here is a test program applying |
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. |
both of the functions defined above to the numbers from 1 to 8. |
||
< |
<syntaxhighlight lang="ursala">#cast %nLW |
||
examples = (fact* <1,2,3,4,5,6,7,8>,fib* <1,2,3,4,5,6,7,8>)</ |
examples = (fact* <1,2,3,4,5,6,7,8>,fib* <1,2,3,4,5,6,7,8>)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 5,312: | Line 5,312: | ||
(with 0 signifying the lowest order of fixed point combinators), |
(with 0 signifying the lowest order of fixed point combinators), |
||
or if that's too easy, then by this definition. |
or if that's too easy, then by this definition. |
||
< |
<syntaxhighlight lang="ursala">#import sol |
||
#fix general_function_fixer 1 |
#fix general_function_fixer 1 |
||
my_fix "h" = "h" my_fix "h"</ |
my_fix "h" = "h" my_fix "h"</syntaxhighlight> |
||
Note that this equation is solved using the next fixed point combinator in the hierarchy. |
Note that this equation is solved using the next fixed point combinator in the hierarchy. |
||
Line 5,322: | Line 5,322: | ||
{{trans|Phix}} |
{{trans|Phix}} |
||
The IIf as translation of Iff can not be used as IIf executes both true and false parts and will cause a stack overflow. |
The IIf as translation of Iff can not be used as IIf executes both true and false parts and will cause a stack overflow. |
||
< |
<syntaxhighlight lang="vb">Private Function call_fn(f As String, n As Long) As Long |
||
call_fn = Application.Run(f, f, n) |
call_fn = Application.Run(f, f, n) |
||
End Function |
End Function |
||
Line 5,359: | Line 5,359: | ||
test "fac" |
test "fac" |
||
test "fib" |
test "fib" |
||
End Sub</ |
End Sub</syntaxhighlight>{{out}} |
||
<pre>fac |
<pre>fac |
||
1 2 6 24 120 720 5040 40320 362880 3628800 |
1 2 6 24 120 720 5040 40320 362880 3628800 |
||
Line 5,366: | Line 5,366: | ||
=={{header|Verbexx}}== |
=={{header|Verbexx}}== |
||
< |
<syntaxhighlight lang="verbexx">/////// Y-combinator function (for single-argument lambdas) /////// |
||
y @FN [f] |
y @FN [f] |
||
Line 5,400: | Line 5,400: | ||
@LOOP init:{ i = -1} while:(i <= 16) next:{i++} |
@LOOP init:{ i = -1} while:(i <= 16) next:{i++} |
||
{ @SAY "fibonacci<" i "> =" (@fibonacci i) };</ |
{ @SAY "fibonacci<" i "> =" (@fibonacci i) };</syntaxhighlight> |
||
=={{header|Vim Script}}== |
=={{header|Vim Script}}== |
||
There is no lambda in Vim (yet?), so here is a way to fake it using a Dictionary. This also provides garbage collection. |
There is no lambda in Vim (yet?), so here is a way to fake it using a Dictionary. This also provides garbage collection. |
||
< |
<syntaxhighlight lang="vim">" Translated from Python. Works with: Vim 7.0 |
||
func! Lambx(sig, expr, dict) |
func! Lambx(sig, expr, dict) |
||
Line 5,426: | Line 5,426: | ||
echo Callx(Callx(g:Y, [g:fac]), [5]) |
echo Callx(Callx(g:Y, [g:fac]), [5]) |
||
echo map(range(10), 'Callx(Callx(Y, [fac]), [v:val])') |
echo map(range(10), 'Callx(Callx(Y, [fac]), [v:val])') |
||
</syntaxhighlight> |
|||
</lang> |
|||
Update: since Vim 7.4.2044 (or so...), the following can be used (the feature check was added with 7.4.2121): |
Update: since Vim 7.4.2044 (or so...), the following can be used (the feature check was added with 7.4.2121): |
||
< |
<syntaxhighlight lang="vim"> |
||
if !has("lambda") |
if !has("lambda") |
||
echoerr 'Lambda feature required' |
echoerr 'Lambda feature required' |
||
Line 5,438: | Line 5,438: | ||
echo Y(Fac)(5) |
echo Y(Fac)(5) |
||
echo map(range(10), 'Y(Fac)(v:val)') |
echo map(range(10), 'Y(Fac)(v:val)') |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre>120 |
<pre>120 |
||
Line 5,444: | Line 5,444: | ||
=={{header|Wart}}== |
=={{header|Wart}}== |
||
< |
<syntaxhighlight lang="python"># Better names due to Jim Weirich: http://vimeo.com/45140590 |
||
def (Y improver) |
def (Y improver) |
||
((fn(gen) gen.gen) |
((fn(gen) gen.gen) |
||
Line 5,457: | Line 5,457: | ||
(n * (f n-1)))))) |
(n * (f n-1)))))) |
||
prn factorial.5</ |
prn factorial.5</syntaxhighlight> |
||
{{omit from|ACL2}} |
{{omit from|ACL2}} |
||
Line 5,466: | Line 5,466: | ||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
{{trans|Go}} |
{{trans|Go}} |
||
< |
<syntaxhighlight lang="ecmascript">var y = Fn.new { |f| |
||
var g = Fn.new { |r| f.call { |x| r.call(r).call(x) } } |
var g = Fn.new { |r| f.call { |x| r.call(r).call(x) } } |
||
return g.call(g) |
return g.call(g) |
||
Line 5,479: | Line 5,479: | ||
System.print("fac(10) = %(fac.call(10))") |
System.print("fac(10) = %(fac.call(10))") |
||
System.print("fib(10) = %(fib.call(10))")</ |
System.print("fib(10) = %(fib.call(10))")</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 5,491: | Line 5,491: | ||
Version 3.0 of the [http://www.w3.org/TR/xpath-30/ XPath] and [http://www.w3.org/TR/xquery-30/ XQuery] specifications added support for function items. |
Version 3.0 of the [http://www.w3.org/TR/xpath-30/ XPath] and [http://www.w3.org/TR/xquery-30/ XQuery] specifications added support for function items. |
||
< |
<syntaxhighlight lang="xquery">let $Y := function($f) { |
||
(function($x) { ($x)($x) })( function($g) { $f( (function($a) { $g($g) ($a)}) ) } ) |
(function($x) { ($x)($x) })( function($g) { $f( (function($a) { $g($g) ($a)}) ) } ) |
||
} |
} |
||
Line 5,500: | Line 5,500: | ||
$fib(6) |
$fib(6) |
||
) |
) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<lang |
<syntaxhighlight lang="xquery">720 8</syntaxhighlight> |
||
=={{header|Yabasic}}== |
=={{header|Yabasic}}== |
||
< |
<syntaxhighlight lang="yabasic">sub fac(self$, n) |
||
if n > 1 then |
if n > 1 then |
||
return n * execute(self$, self$, n - 1) |
return n * execute(self$, self$, n - 1) |
||
Line 5,532: | Line 5,532: | ||
test("fac") |
test("fac") |
||
test("fib")</ |
test("fib")</syntaxhighlight> |
||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
< |
<syntaxhighlight lang="zkl">fcn Y(f){ fcn(g){ g(g) }( 'wrap(h){ f( 'wrap(a){ h(h)(a) }) }) }</syntaxhighlight> |
||
Functions don't get to look outside of their scope so data in enclosing scopes needs to be bound to a function, the fp (function application/cheap currying) method does this. 'wrap is syntactic sugar for fp. |
Functions don't get to look outside of their scope so data in enclosing scopes needs to be bound to a function, the fp (function application/cheap currying) method does this. 'wrap is syntactic sugar for fp. |
||
< |
<syntaxhighlight lang="zkl">fcn almost_factorial(f){ fcn(n,f){ if(n<=1) 1 else n*f(n-1) }.fp1(f) } |
||
Y(almost_factorial)(6).println(); |
Y(almost_factorial)(6).println(); |
||
[0..10].apply(Y(almost_factorial)).println();</ |
[0..10].apply(Y(almost_factorial)).println();</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 5,545: | Line 5,545: | ||
L(1,1,2,6,24,120,720,5040,40320,362880,3628800) |
L(1,1,2,6,24,120,720,5040,40320,362880,3628800) |
||
</pre> |
</pre> |
||
< |
<syntaxhighlight lang="zkl">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(); |
Y(almost_fib)(9).println(); |
||
[0..10].apply(Y(almost_fib)).println();</ |
[0..10].apply(Y(almost_fib)).println();</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |