如何使用Swift中的函数参数消除对泛型函数的调用的歧义?
我正在编写一个解析器类,它希望以特定的顺序读取一系列标记。语法中的某些产品具有可选的非终端,因此我想创建一个通用的“maybe”函数,该函数可以作为回调传递给负责解析非终端的函数。通常,函数会在失败时抛出错误,但由于在某些情况下它是可选的,因此maybe函数会抑制错误。然而,Swift提供了一个错误“表达式的类型在没有更多上下文的情况下是不明确的”,我无法找出正确的类型转换和/或键入来消除歧义 以下是我为重新创建错误所能编写的最少代码量:如何使用Swift中的函数参数消除对泛型函数的调用的歧义?,swift,generics,ambiguous,Swift,Generics,Ambiguous,我正在编写一个解析器类,它希望以特定的顺序读取一系列标记。语法中的某些产品具有可选的非终端,因此我想创建一个通用的“maybe”函数,该函数可以作为回调传递给负责解析非终端的函数。通常,函数会在失败时抛出错误,但由于在某些情况下它是可选的,因此maybe函数会抑制错误。然而,Swift提供了一个错误“表达式的类型在没有更多上下文的情况下是不明确的”,我无法找出正确的类型转换和/或键入来消除歧义 以下是我为重新创建错误所能编写的最少代码量: public struct VariableDeclar
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标识符:标识符
公共let类型:String?
}
公共结构标识符{}
公共类解析器{
public func parseVariableDeclaration()抛出->VariableDeclaration{
让标识符=尝试self.parseIdentifier()
让type=self.maybe(self.parseType)
返回变量声明(标识符:标识符,类型:类型)
}
public func parseIdentifier()抛出->标识符{return Identifier()}
public func parseType()抛出->字符串{return”“}
公共函数可能(uu回调:(解析器)->()抛出->T)->T{
做{
返回try回调(self)()
}
抓住{
归零
}
}
}
以下是我在消除问题行歧义方面的一些失败尝试:
let type: String? self.maybe(self.parseType)
let type = self.maybe(self.parseType) as String?
let type = self.maybe<String>(self.parseType)
let类型:字符串?self.maybe(self.parseType)
让type=self.maybe(self.parseType)作为字符串?
让type=self.maybe(self.parseType)
这里的问题不是通用参数。第一次和第二次尝试将告诉编译器T
应该是什么类型
问题是作为回调传递的值,该值具有以下签名:
(解析器)->()抛出->T
您正在传入具有以下签名的self.parseType
:
()抛出->字符串
使用Self.parseType
(注意大写的S
)或Parser.parseType
作为回调的值是可行的
或者,您可以这样定义可能:
let type = self.maybe(Parser.parseType)
public func可能(uCallback:(解析器)抛出->T)->T?{
做{
返回尝试回调(self)
}抓住{
归零
}
}
然后这样称呼它:
let type = self.maybe(Parser.parseType)
let type=self.maybe{try$0.parseType()}
我不确定这是否真的是你想要做的,但是如果你想保留的签名,也许
,你需要像这样传递方法的部分引用:
let type = self.maybe(Parser.parseType)
我无法编译Self.parseType
(它拒绝将Self
转换为Parser
),但Parser.parseType
工作成功。lambda的建议也起了作用。谢谢您的全面回复。@Jared啊,那是因为解析器
是一个(非最终)类。因此子类中的Self
将不是(精确的)解析器
。。。