【问题标题】:Porting Underscore's some function to swift将 Underscore 的一些功能移植到 swift
【发布时间】:2017-08-05 14:13:29
【问题描述】:

作为学习练习,我将 Underscore.js 的一些实用功能移植到 swift 中,我从 some 开始,如果集合中的任何元素通过给定的集合块,则返回 true。

天真的实现:

extension Sequence {
    func some(_ predicate: (Self.Iterator.Element) -> Bool) -> Bool {
        return reduce(false) { $0 || predicate($1) }
    }
}

然而,我注意到很多 STL 函数包括 throwsrethrows。一个很好的例子是 filter 函数,它的函数签名为:

func filter(_ isIncluded: (Element) throws -> Bool) rethrows -> [Element]

有人可以告诉我如何编写some 函数,同时还利用throwrethrows 功能吗?

【问题讨论】:

    标签: ios swift functional-programming


    【解决方案1】:

    这篇博文是一个很好的概述:http://robnapier.net/re-throws

    基本上,rethrows 是一个指示函数,它仅在其闭包参数之一抛出时才会抛出。如果您使用不抛出的闭包调用函数,这会强制您不必处理抛出。在您的情况下,您只需将扩展方法定义为:

    extension Sequence {
        func some(_ predicate: (Self.Iterator.Element) throws -> Bool) rethrows -> Bool {
            return reduce(false) { $0 || try predicate($1) }
        }
    }
    

    现在,some 将接受一个 throwing 或 non-throw 谓词,如果你给它一个 non-throw 谓词,你就不必担心 try

    【讨论】:

    • 我确实尝试过,但编译失败说“调用可以抛出但没有用 try 标记”,这是有道理的。我确实想出了如何通过结合使用mapreduce来完成它,我会发布一个答案来分享。
    • 哎呀。我忘了在谓词调用前面放一个try。我会更新代码。
    【解决方案2】:

    我最终能够通过结合使用mapreduce 来解决我的问题。我做了一个快速操场:

    extension Sequence {
        func some(_ predicate: (Self.Iterator.Element) throws -> Bool) rethrows -> Bool {
            return try map(predicate).reduce(false) { $0 || $1 }
        }
    }
    
    let list = [1, 2, 3]
    list.some({ $0 == 1 }) // true
    list.some({ $0 % 50 == 0 }) // false
    

    使用 map,您将谓词应用于每个元素,将整个数组映射到一个布尔数组,然后将它们 OR'ing 在一起。

    这不是最有效的算法,并且可以进行一些明确的优化,例如在遇到true 值时立即返回等,但我确实喜欢该解决方案的简单功能性质。

    【讨论】:

      猜你喜欢
      • 2021-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多