如何快速编写非/求高阶函数?

时间:2018-12-30 04:40:57

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

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

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

我正试图迅速地做同样的事情:

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

我在做什么错了?

2 个答案:

答案 0 :(得分:3)

使用SELECT DISTINCT TP.PRODID AS ID, TP.PRODNAME AS NAME, TP.LANG AS LANG, TP.FMT, TP.TYPE FROM PDF_DETAILS TP WHERE TP.PRODID = @PRODID AND (@PRODUCTNAME IS NULL OR REPLACE(REPLACE(REPLACE(REPLACE(TP.PRODNAME, '™', '|TM'), '®', '|TS'), '©', '|CP'), '°', '|DEG') LIKE REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PRODNAME, '[', '\['), '_', '\_'), '™', '|TM'), '®', '|TS'), '©', '|CP'), '°', '|DEG') ESCAPE '\' UNION ALL SELECT DISTINCT TP.PRODID AS ID, TP.PRODNAME AS NAME, TP.LANG AS LANG, TP.FMT, TP.TYPE FROM HTML_DETAILS TP WHERE TP.PRODID = @PRODID AND (@PRODUCTNAME IS NULL OR REPLACE(REPLACE(REPLACE(REPLACE(TP.PRODNAME,'™','|TM'),'®','|TS'),'©','|CP'),'°','|DEG') LIKE REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@PRODNAME,'[','\['),'_','\_'),'™','|TM'),'®','|TS'),'©','|CP'),'°','|DEG') ESCAPE '\' 是一种代码味道。您可以直接扩展Collection:

Any

您对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) }
}

答案 1 :(得分:2)

您有两个错误:

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

尝试一下:

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

请注意,在此版本中,我没有将谓词参数使用参数名称。您在声明((A) -> 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不支持。