如何在Swift中使用函数参数消除对该泛型函数的调用的歧义?

问题描述

我正在编写一个解析器类,该类希望以特定顺序读取令牌序列。其语法中的某些产品具有非终结符,这些非终结符是可选的,因此我想制作一个通用的“也许”函数,可以将该函数传递给负责将非终结符解析为回调的函数。通常,该函数会在失败时引发错误,但是由于在某些情况下它是可选的,所以mayby函数会抑制该错误。但是,Swift提供了错误“表达式类型在没有更多上下文的情况下是模棱两可的”,我无法找出正确的类型转换和/或类型来消除歧义。

这是我能够编写以重新创建错误的最少代码:

public struct VariableDeclaration {
    public let identifier: Identifier
    public let type: String?
}

public struct Identifier { }

public class Parser {
    
    public func parseVariableDeclaration() throws -> VariableDeclaration {
        let identifier = try self.parseIdentifier()
        let type = self.maybe(self.parseType)
        return VariableDeclaration(identifier: identifier,type: type)
    }
    
    public func parseIdentifier() throws -> Identifier { return Identifier() }
    
    public func parseType() throws -> String { return "" }
    
    public func maybe<T>(_ callback: (Parser) -> () throws -> T) -> T? {
        do {
            return try callback(self)()
        }
        catch {
            return nil
        }
    }
}

以下是我在消除问题线歧义方面的一些失败尝试:

let type: String? self.maybe(self.parseType)
let type = self.maybe(self.parseType) as String?
let type = self.maybe<String>(self.parseType)

解决方法

这里的问题不是通用参数。您的第一次和第二次尝试将告诉编译器T应该是什么类型。

问题在于您作为callback传递的值具有以下签名:

(Parser) -> () throws -> T

您正在传递具有以下签名的self.parseType

() throws -> String

有效的方法是使用Self.parseType(注意大写字母S)或Parser.parseType作为callback的值。

或者,您可以像这样定义maybe

public func maybe<T>(_ callback: (Parser) throws -> T) -> T? {
    do {
        return try callback(self)
    } catch {
        return nil
    }
}

然后这样称呼它:

let type = self.maybe { try $0.parseType() }
,

我不确定这是否真的是您想要的,但是如果您想保留maybe的签名,则需要传递方法的部分引用,如下所示:

        let type = self.maybe(Parser.parseType)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...