问题描述
我正在编写一个解析器类,该类希望以特定顺序读取令牌序列。其语法中的某些产品具有非终结符,这些非终结符是可选的,因此我想制作一个通用的“也许”函数,可以将该函数传递给负责将非终结符解析为回调的函数。通常,该函数会在失败时引发错误,但是由于在某些情况下它是可选的,所以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)