如何在 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)
我正在编写一个解析器 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)