函数中的Swift泛型类型+高阶函数

时间:2018-02-08 09:50:27

标签: swift generics higher-order-functions

假设我有一个通用的方法来进行一些带有输入和输出的转换,部分过程流需要一个块(也使用泛型I和O)来处理它。

func run<I : Codable, O : Codable>(_ inputType: I, _ outputType: O, _ converter : (_ input: I)-> O) throws -> Void
{ 
    // do something to input I

    let output : O = converter(input)

    // do something else to output O
}

问题是,我无法像示例一样调用此方法:

run(InputObj, OutputObj) { (input) -> Codable in
        var outputObj = OutputObj( ... )
        // do something here
        return outputObj
}

并显示错误:

  

无法转换类型'() - &gt;的值Codable'到   预期参数类型'() - &gt; _'

我也尝试将块的返回类型“Codable”更改为“OutputObj”。

感谢是否有人可以提供帮助。

2 个答案:

答案 0 :(得分:1)

您不需要在类上创建此方法。问题中简化代码中的问题是闭包是显式输入的,以便返回package identity name,但在答案中的代码中,它会键入以返回Codable

如果在示例中删除闭包的显式返回类型 - 并依赖于从OutputObjinput参数推断出的类型 - 代码无需进一步修改即可工作。

output

此外,还有一些关于Swift风格改进的建议:

  • 返回try run(inputObj, outputObj) { input in // do something and return an output object } 是多余的,因此您可以从Void函数声明中删除它。
  • Swift通常会尝试描述/命名其通用参数。例如,runOptional<Wrapped>Array<Element>。在您的情况下,Dictionary<Key, Value>Input会比OutputI更具描述性。
  • Swift通常不会在类型或变量名称中使用O后缀,并且传递给此函数的参数不是类型,它们是值/实例。在这种情况下,Typeinput将是两个参数的惯用名。
  • 如果从参数类型中可以清楚地看出哪一个是输入,哪一个是输出,那么未标记的参数与Swift命名准则相匹配。否则,调用站点使用带标签的参数更清晰(在参数名称之前没有output)。

通过这些更改,_函数声明将如下所示:

run

答案 1 :(得分:0)

OK!

我找到了解决这个问题的方法。 我为函数“run”创建了一个类

class Converter<I : Codable, O : Codable> {
    func run(_ converter : (_ input: I)-> O) throws -> Void
}

然后按

打电话
let converter : Converter = Converter<InputObj, OutputObj>()
run() { (input) -> OutputObj in
    var outputObj = OutputObj( ... )
    // do something here
    return outputObj
}

现在任何一切都完美无缺!