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

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

[C++][SFML 2.2] Strange Performance Issues - Moving Mouse Lowers CPU Usage -

ios - Possible to get UIButton sizeThatFits to work? -