Skip to content

Instantly share code, notes, and snippets.

@hooman
Last active October 22, 2015 17:03
Show Gist options
  • Save hooman/d8629fb001798d3bee6e to your computer and use it in GitHub Desktop.
Save hooman/d8629fb001798d3bee6e to your computer and use it in GitHub Desktop.
/// Y-Combinator for creating recursive closures.
///
/// :param: `In` Arbitrary input parameter type(s) of the closure.
/// :param: `Out` Arbitrary return type (including `Void`) of the closure.
/// :param: `f` represents the recursive closure.
/// :returns: Returns a recursive closure.
///
/// It is used with a pair of closures: An outer closure that names the inner closure (`f`)
/// and lets the inner closure recurse on itself by capturing itself using the parameter of
/// the outer closure (`f`). For example:
///
/// .. parsed-literal::
///
/// let fac = Y { f in { x in
///
/// /* f(x) = */ x < 2 ? 1 : x * f(x - 1)
/// }}
///
/// **Note:** `In` and `Out` can be arbitrary tuples, hence you may have arbitrary number and
/// type of arguments and return values for the closure. Including empty tuple `()` or `Void`.
///
func Y <In, Out> ( f: (In->Out) -> (In->Out) ) -> (In->Out) {
return { x in f(Y(f))(x) }
}
// A couple of examples to try in a playground:
let fac = Y { f in { n in
n < 2 ? 1 : n * f(n - 1)
}}
let fib = Y { f in { n in
n <= 2 ? 1 : f(n-1) + f(n-2)
}}
@GarthSnyder
Copy link

This translates beautifully to Swift, doesn't it? A useful reference for anyone looking at this: http://mvanier.livejournal.com/2897.html.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment