问题描述
以下sum函数的两个变体是我试图重复Abelson和Sussman在Swift中经典的计算机程序结构和解释一书中介绍的lisp版本。第一个版本用于计算范围内整数的总和,或一个范围内整数的平方和,第二个版本用于计算pi / 8的近似值。
我无法将这些版本合并为一个可处理所有类型的func。
code>和 Int 因此协议一致性很简单:
扩展名Double:Addable {}
扩展名Int:可添加{}
提供一个中性元素:
扩展名Int:NeutralAdditionElementProvider {
static func neutralAdditionElement() - > Int {
return 0
}
}
扩展名Double:NeutralAdditionElementProvider {
static func neutralAdditionElement() - > Double {
return 0.0
}
}
The two variants of the sum function below are my attempt to repeat the lisp version introduced by Abelson and Sussman in the classic "Structure and interpretation of Computer Programs" book in Swift. The first version was used to compute the sum of integers in a range, or the sum of squares of integers in a range, and the second version was used to compute the approximation to pi/8.
I was not able to combine to the versions into a single func which will handle all types. Is there a clever way to use generics or some other Swift language feature to combine the variants?
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)) }with
sum({$0}, 1, {$0 + 1}, 3)6 as result
sum({$0 * $0}, 3, {$0 + 1}, 4)25 as result
8.0 * sum({1.0 / Float(($0 * ($0 + 2)))}, 1, {$0 + 4}, 2500)3.14079 as result
解决方案To make it a bit easier I have changed the method signatures slightly and assume that it is good enough to work for func sum_ <T> (term: (T -> T), a: T, next: (T -> T), b: T) -> T {, where T is some kind of number.
Unfortunately there is no Number type in Swift, so we need to make our own. Our type needs to support
- addition
- comparison
- 0 (the neutral element for addition)
New Protocols for the requirements of the function
Comparison is handled in the Comparable protocol, for the reset we can create our own protocols:
protocol NeutralAdditionElementProvider { class func neutralAdditionElement () -> Self } protocol Addable { func + (lhs: Self, rhs: Self) -> Self }
sum implementation
We can now implement the sum function:
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) }
Making Int and Double conform to the protocols
+ is already implemented for Double and Int so protocol conformance is easy:
extension Double: Addable {} extension Int: Addable {}
Providing a neutral element:
extension Int: NeutralAdditionElementProvider { static func neutralAdditionElement() -> Int { return 0 } } extension Double: NeutralAdditionElementProvider { static func neutralAdditionElement() -> Double { return 0.0 } }
这篇关于泛型和Swift中的函数式编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!