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

How do I disambiguate this call to a generic function with a function parameter in Swift?

我正在编写一个解析器 class,它希望以特定顺序读取一系列标记。其语法中的某些产生式具有可选的非终端,因此我想制作一个通用的“可能”函数,该函数可以传递给负责将非终端解析为回调的函数。通常,该函数会在失败时抛出错误,但由于在某些情况下它是可选的,因此 maybe 函数会抑制错误。但是,Swift 提供错误“没有更多上下文,表达式类型不明确”,我无法找出正确的转换集 and/or 打字来消除歧义。

这是我能够编写的用于重现错误的最少代码量:

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 [=13=].parseType() }

我不确定这是否真的是你想要做的,但如果你想保留 maybe 的签名,你需要像这样传递方法的部分引用:

        let type = self.maybe(Parser.parseType)