Recursion over a Swift Sliceable

前端 未结 3 981
南旧
南旧 2021-01-12 06:38

I feel that I must be missing something obvious. Decomposing a list into the head and tail and then recursing over the tail is a standard functional programming technique, y

3条回答
  •  北荒
    北荒 (楼主)
    2021-01-12 06:58

    It turns out that there is a generic solution. You need to add these generic requirements:

    <  
      S : Sliceable where S.SubSlice : Sliceable,  
      S.SubSlice.Generator.Element == S.Generator.Element,  
      S.SubSlice.SubSlice == S.SubSlice  
      >
    

    For the question posted, this gives:

    func recurseSeq<
        S : Sliceable where S.SubSlice : Sliceable,
        S.SubSlice.Generator.Element == Int,
        S.SubSlice.SubSlice == S.SubSlice,
        S.Generator.Element == Int
        >(list: S) -> [Int] {
    
        guard let first = list.first else {
            return []
        }
    
        let rest = recurseSeq(dropFirst(list))
        let next = rest.first ?? 0
    
        return [first + next] + rest
    }
    

    Here's a useful generic reduce on any sliceable:

    extension Sliceable where  
      SubSlice : Sliceable,  
      SubSlice.Generator.Element == Generator.Element,  
      SubSlice.SubSlice == SubSlice {  
    
      func recReduce(combine: (Generator.Element, Generator.Element) -> Generator.Element) -> Generator.Element? {  
    
        return self.first.map {  
          head in  
          dropFirst(self)  
            .recReduce(combine)  
            .map {combine(head, $0)}  
            ?? head  
        }  
      }  
    }  
    [1, 2, 3].recReduce(+) // 6  
    

    I can't take credit for this, the solution was posted on the Apple Development Forums.

    It's a shame that the generic requirements are so involved for such a a basic operation - it's hardly intuitive! But I'm glad to have a solution...

提交回复
热议问题