【问题标题】:How do I write the not/negate higher order function in swift?如何快速编写非/否定高阶函数?
【发布时间】:2018-12-30 04:40:57
【问题描述】:

我是一名 Javascripter,我喜欢使用 not/negate 函数:

function not (predicateFunc) {
    return function () {
        return !predicateFunc.apply(this, arguments);
    };
}

我正在尝试用 swift 做同样的事情:

func not <A> (_ f: @escaping (_ A: Any) -> Bool) -> (A) -> Bool {
    return { a in !f(a) }
}

但是我遇到了类似的错误

generic parameter 'T' could not be inferred

Cannot convert value of type '(_) -> Bool' to expected argument type '(Any) -> Bool'

我正在寻找的结果是当我有这样的功能时:

func isEmpty<T: Collection>(collection: T) -> Bool {
    return collection.count == 0
}

我可以像这样创建一个notEmpty 函数:

let notEmpty = not(isEmpty)

然后像这样使用它

   notEmpty([3,4,5]) // true

我做错了什么?

【问题讨论】:

    标签: swift functional-programming higher-order-functions


    【解决方案1】:

    使用Any 是一种代码味道。您可以直接扩展 Collection:

    extension Collection {
        var notEmpty: Bool {
            return !isEmpty
        }
    }
    
    [1, 3, 5].notEmpty // true
    

    not 的函数定义可以这样工作:

    func not <A> (_ f: @escaping (_ a: A) -> Bool) -> (A) -> Bool {
        return { a in !f(a) }
    }
    

    但要调用它,你需要这样的东西:

    let arrayNotEmpty = not { (array: [Int]) in array.isEmpty }
    arrayNotEmpty([1, 3, 5]) // true
    

    【讨论】:

    • 不是我想要的。我仍然想使用通用集合而不是array: [Int]。没有更好的办法吗?
    【解决方案2】:

    你有两个错误:

    • 您将A 用作类型参数和参数名称。
    • 您使用 Any 作为参数类型,而不是使用类型参数 (A) 作为参数类型。

    试试这个:

    func not<A>(predicate: @escaping (A) -> Bool) -> (A) -> Bool {
        return { !predicate($0) }
    }
    

    请注意,在这个版本中,我没有为谓词参数使用参数名称。声明中不需要参数名称 ((A) -&gt; Bool),我在正文中使用匿名参数名称 ($0)。


    好的,所以你想写这个:

    func isEmpty<T: Collection>(collection: T) -> Bool {
        return collection.count == 0
    }
    
    func not<A>(_ predicate: @escaping (A) -> Bool) -> (A) -> Bool {
        return { !predicate($0) }
    }
    
    let notEmpty = not(isEmpty)
    

    你得到这个错误:

    let notEmpty = not(isEmpty)
                   ^ Generic parameter 'A' could not be inferred
    

    问题是这段代码试图创建一个泛型闭包,但 Swift 不支持泛型闭包。

    也就是说,nonEmpty 的类型会是什么?它会是这样的:

    <A: Collection>(A) -> Bool
    

    而 Swift 不支持。

    【讨论】:

    • 不错!但我收到编译器错误:generic parameter 'A' could not be inferred
    • @AmitErandole 显然在声明中你必须告诉类型编译为let notEmpty: ([Int])-&gt; Bool = not(isEmpty)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多