Generics and Functional programming in Swift -
the 2 variants of sum function below attempt repeat lisp version introduced abelson , sussman in classic "structure , interpretation of computer programs" book in swift. first version used compute sum of integers in range, or sum of squares of integers in range, , second version used compute approximation pi/8.
i not able combine versions single func handle types. there clever way use generics or other swift language feature combine variants?
func sum(term: (int) -> int, a: int, next: (int) -> int, b: int) -> int { if > 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 > b { return 0 } return (term(a) + sum(term, next(a), next, b)) } with
sum({$0}, 1, {$0 + 1}, 3) 6 result
sum({$0 * $0}, 3, {$0 + 1}, 4) 25 result
8.0 * sum({1.0 / float(($0 * ($0 + 2)))}, 1, {$0 + 4}, 2500) 3.14079 result
to make bit easier have changed method signatures , assume enough work func sum_ <t> (term: (t -> t), a: t, next: (t -> t), b: t) -> t {, t kind of number.
unfortunately there no number type in swift, need make our own. our type needs support
- addition
- comparison
0(the neutral element addition)
new protocols requirements of function
comparison handled in comparable protocol, reset can create our own protocols:
protocol neutraladditionelementprovider { class func neutraladditionelement () -> self } protocol addable { func + (lhs: self, rhs: self) -> self } sum implementation
we can implement sum function:
func sum <t t:addable, t:neutraladditionelementprovider, t:comparable> (term: (t -> t), a: t, next: (t -> t), b: t) -> t { if > b { return t.neutraladditionelement() } return term(a) + sum(term, next(a), next, b) } making int , double conform protocols
+ implemented double , int protocol conformance easy:
extension double: addable {} extension int: addable {} providing neutral element:
extension int: neutraladditionelementprovider { static func neutraladditionelement() -> int { return 0 } } extension double: neutraladditionelementprovider { static func neutraladditionelement() -> double { return 0.0 } }
Comments
Post a Comment