zvw*_*iss 4 generics functional-programming swift
下面 sum 函数的两个变体是我尝试用 Swift 重复 Abelson 和 Sussman 在经典的《计算机程序的结构和解释》一书中介绍的 lisp 版本。第一个版本用于计算某个范围内的整数之和,或某个范围内的整数的平方和,第二个版本用于计算 pi/8 的近似值。
我无法将这些版本组合成一个可以处理所有类型的函数。有没有一种巧妙的方法来使用泛型或其他一些 Swift 语言功能来组合变体?
func sum(term: (Int) -> Int, a: Int, next: (Int) -> Int, b: Int) -> Int {
if a > b {
return 0
}
return (term(a) + sum(term, next(a), next, b))
}
func sum(term: (Int) -> Float, a: Int, next: (Int) -> Int, b: Int) -> Float {
if a > b {
return 0
}
return (term(a) + sum(term, next(a), next, b))
}
Run Code Online (Sandbox Code Playgroud)
和
sum({$0}, 1, {$0 + 1}, 3)
Run Code Online (Sandbox Code Playgroud)
结果 6
sum({$0 * $0}, 3, {$0 + 1}, 4)
Run Code Online (Sandbox Code Playgroud)
结果 25
8.0 * sum({1.0 / Float(($0 * ($0 + 2)))}, 1, {$0 + 4}, 2500)
Run Code Online (Sandbox Code Playgroud)
结果为 3.14079
为了使其更容易一些,我稍微更改了方法签名,并假设它足以适用于func sum_ <T> (term: (T -> T), a: T, next: (T -> T), b: T) -> T {,其中 T 是某种数字。
不幸的是,Swift 中没有Number类型,所以我们需要创建自己的类型。我们的类型需要支持
0(添加中性元素)比较是在Comparable协议中处理的,对于重置,我们可以创建自己的协议:
protocol NeutralAdditionElementProvider {
class func neutralAdditionElement () -> Self
}
protocol Addable {
func + (lhs: Self, rhs: Self) -> Self
}
Run Code Online (Sandbox Code Playgroud)
sum执行我们现在可以实现该sum功能:
func sum <T where T:Addable, T:NeutralAdditionElementProvider, T:Comparable> (term: (T -> T), a: T, next: (T -> T), b: T) -> T {
if a > b {
return T.neutralAdditionElement()
}
return term(a) + sum(term, next(a), next, b)
}
Run Code Online (Sandbox Code Playgroud)
Int并Double遵守协议+已经实现了Double,Int因此协议一致性很容易:
extension Double: Addable {}
extension Int: Addable {}
Run Code Online (Sandbox Code Playgroud)
提供中性元素:
extension Int: NeutralAdditionElementProvider {
static func neutralAdditionElement() -> Int {
return 0
}
}
extension Double: NeutralAdditionElementProvider {
static func neutralAdditionElement() -> Double {
return 0.0
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
550 次 |
| 最近记录: |