3

我正在尝试创建一个 lambda 函数来获取阶乘函数,但这会引发分段错误和错误。我如何让这个在 Swift 中工作。请查看此视频以了解我正在尝试做的事情http://www.confreaks.com/videos/1287-rubyconf2012-y-not-adventures-in-functional-programming

typealias f = () -> ()
typealias g = (Int) -> (Int)
typealias F = Any -> g

let y = { (gen: Any) -> g in
    (gen as F)(gen)
}
let fact = y({ (gen: Any) -> g in
    { (n: Int) -> Int in
        if n == 0 {
            return 1
        } else {
            return n * (gen as F)(gen)(n - 1)
        }
    }
})

fact(10)
4

2 回答 2

1

xiliangchen有一篇很棒的文章介绍了如何在 Swift 中创建 Y-combinator。(从技术上讲,这不是 Y组合器,因为它是显式递归的,但它在很大程度上可以满足您的需求。)这是该 Y 函数的示例(为了清楚起见,去掉了它的通用规范):

typealias G = Int -> Int

func Y (f: G -> G) -> G {
    return {
        (i: Int) -> Int in
        f(Y(f))(i)
    }
}

let factorial = Y { (f: G) -> G in
    { (n: Int) -> Int in
        if n == 0 {
            return 1
        } else {
            return n * f(n - 1)
        }
    }
}

factorial(5)        // 120

有关 Y 组合器的更多信息,您可以查看Mike Vanier 的这篇很棒的(长篇)作品

注意:使用Any有点混乱——我建议尽可能避开它,特别是因为在这种情况下你不需要它。)

于 2014-09-26T14:51:17.967 回答
1

您可以使用递归类型实现真正的(没有显式递归)Y 组合器,没有任何不安全的技巧(Rosetta Code的学分):

struct RecursiveFunc<F> {
  let o : RecursiveFunc<F> -> F
}

func Y<A, B>(f: (A -> B) -> A -> B) -> A -> B {
  let r = RecursiveFunc<A -> B> { w in f { w.o(w)($0) } }
  return r.o(r)
}

let factorial = Y { (f: Int -> Int) -> Int -> Int in
  { $0 <= 1 ? 1 : $0 * f($0-1) }
}
println(factorial(10))

Any并没有真正帮助,因为Any不能表示函数类型

更新:从 Xcode 6.1 beta 3 开始,Any可以表示函数类型,并且您的代码可以正确编译和工作。

于 2014-09-26T18:54:48.723 回答