3

看下面两个表达式:

baz(Foo<Bar, Bar>(0))
baz(Foo < Bar, Bar > (0))

在不知道什么、bazFooBarbaz可以是类型或方法,FooBar可以是类型或变量)的情况下,无法区分 是<表示类型参数列表还是小于运算符。

// two different outcomes, difference shown with parentheses
baz((Foo<Bar,Bar>(0)))      // generics
baz((Foo < Bar), (Bar > 0)) // less-than

任何理智的编程语言在解析这样的表达式时都不应该依赖 what baz, Fooand are 。Bar然而,无论我在哪里放置空格,Swift 都设法消除了以下表达式的歧义:

println(Dictionary<String, String>(0))
println(Dictionary < String, String > (0))

编译器如何管理这个?而且,更重要的是,在 Swift 语言规范中是否有任何位置。描述此规则的地方。翻阅Language ReferenceSwift 书的部分,我只找到了这一部分:

在某些构造中,带有前导<或的运算符>可能被拆分为两个或多个标记。其余部分以相同方式处理,可以再次拆分。因此,无需使用空格来消除>诸如Dictionary<String, Array<Int>>. 在此示例中,结束>字符不被视为单个标记,然后可能会被误解为位移>>运算符。

certain constructs在这种情况下指的是什么?实际的语法只包含一个提及类型参数的产生式规则:

显式成员表达式 → 后缀表达式.标识符generic-argument-clause opt

任何解释或资源将不胜感激。

4

1 回答 1

5

感谢@Martin R,我找到了编译器源代码的相关部分,其中包含解释它如何解决歧义的注释。

swift/ParseExpr.cpp,第 1533 行

///   The generic-args case is ambiguous with an expression involving '<'
///   and '>' operators. The operator expression is favored unless a generic
///   argument list can be successfully parsed, and the closing bracket is
///   followed by one of these tokens:
///     lparen_following rparen lsquare_following rsquare lbrace rbrace
///     period_following comma semicolon

基本上,编译器尝试解析类型列表,然后检查右尖括号后的标记。如果该令牌是

  • 右括号、方括号或大括号,
  • 一个左括号、括号或句点,其自身和右尖括号之间没有空格(>(, >[,但不是> (, > [),
  • 开口大括号或
  • 逗号或分号

它将表达式解析为通用调用,否则将其解析为一个或多个关系表达式。

Annotated C#一书中所述,该问题在 C# 中以类似的方式解决。

于 2016-04-03T17:49:55.843 回答