find()使用函数式编程

Dan*_*iel 5 generics functional-programming swift

我想创建一个通常用于函数式编程的通用find().在函数式编程中,您不能使用数组索引和for循环.你过滤了.它的工作方式是,如果你有一个说清单

["apple", "banana", "cherry"] 
Run Code Online (Sandbox Code Playgroud)

并且您想要找到banana,然后通过创建元组将数组索引分配给列表元素

[(1, "apple"), (2, "banana"), (3, "cherry")] 
Run Code Online (Sandbox Code Playgroud)

现在,您可以过滤到"banana"并返回索引值.

我试图为此创建一个通用函数,但我收到一个错误.这个语法出了什么问题?

func findInGenericIndexedList<T>(indexedList: [(index: Int, value: T)], element: (index: Int, value: T)) -> Int? {        
    let found = indexedList.filter {   // ERROR: Cannot invoke 'filter' with an argument list of type '((_) -> _)'

        element.value === $0.value
    }

    if let definiteFound = found.first {
        return definiteFound.index
    }
    return nil
}
Run Code Online (Sandbox Code Playgroud)

更新1:我想使用上面的解决方案而不是使用find()(将被弃用)或者使用Swift 2.0 indexOf(),因为我试图遵循功能编程范例,依赖于通用函数而不是类方法.

Tri*_*ide 2

完成这项工作所需的最小更改是使 T 符合 Equatable 并使用 == 运算符。

func findInGenericIndexedList<T:Equatable>(indexedList: [(index: Int, value: T)], element: (index: Int, value: T)) -> Int? {
    let found = indexedList.filter {
        element.value == $0.value
    }

    if let definiteFound = found.first {
        return definiteFound.index
    }
    return nil
}
Run Code Online (Sandbox Code Playgroud)

在这里使用 === 并没有什么意义,因为通常会将其应用于值类型(特别是如果您遵循函数范式),而这从来都不是真的。

除此之外,我花了一些时间思考这个问题,这就是我会做的:

extension Array where Element : Equatable {
    func find(element:Array.Generator.Element) -> Int? {
        let indexedList = lazy(self.enumerate())
        let found = indexedList.filter {
            element == $1
        }

        let definiteFound = found.prefix(1)
        return definiteFound.generate().next()?.index
    }
}
Run Code Online (Sandbox Code Playgroud)

数组上的协议扩展,因为它使语法更整洁,惰性序列避免检查每个元素,0 索引。