Swift 如何消除表达式上下文中类型参数的歧义?
How does Swift disambiguate Type Arguments in Expression Contexts?
看看下面两个表达式:
baz(Foo<Bar, Bar>(0))
baz(Foo < Bar, Bar > (0))
不知道是什么,baz
、Foo
和 Bar
是(baz
可以是类型或方法,Foo
和 Bar
可以是类型或变量),无法区分 <
表示类型参数列表还是小于运算符。
// two different outcomes, difference shown with parentheses
baz((Foo<Bar,Bar>(0))) // generics
baz((Foo < Bar), (Bar > 0)) // less-than
任何理智的编程语言在解析这样的表达式时都不应该依赖于 baz
、Foo
和 Bar
。然而,无论我在哪里放置空格,Swift 都设法消除了以下表达式的歧义:
println(Dictionary<String, String>(0))
println(Dictionary < String, String > (0))
编译器如何管理这个?而且,更重要的是,Swift 语言规范中是否有任何位置。其中描述了规则。翻阅Swift书的Language Reference
部分,只找到这一段:
In certain constructs, operators with a leading <
or >
may be split into two or more tokens. The remainder is treated the same way and may be split again. As a result, there is no need to use whitespace to disambiguate between the closing >
characters in constructs like Dictionary<String, Array<Int>>
. In this example, the closing >
characters are not treated as a single token that may then be misinterpreted as a bit shift >>
operator.
在此上下文中,certain constructs
指的是什么?实际语法只包含一个提到类型参数的产生式规则:
explicit-member-expression → postfix-expression .
identifiergeneric-argument-clauseopt
任何解释或资源将不胜感激。
感谢@Martin R,我找到了编译器源代码的相关部分,其中包含解释它如何解决歧义的注释。
swift/ParseExpr.cpp
, line 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#中以类似的方式解决。
看看下面两个表达式:
baz(Foo<Bar, Bar>(0))
baz(Foo < Bar, Bar > (0))
不知道是什么,baz
、Foo
和 Bar
是(baz
可以是类型或方法,Foo
和 Bar
可以是类型或变量),无法区分 <
表示类型参数列表还是小于运算符。
// two different outcomes, difference shown with parentheses
baz((Foo<Bar,Bar>(0))) // generics
baz((Foo < Bar), (Bar > 0)) // less-than
任何理智的编程语言在解析这样的表达式时都不应该依赖于 baz
、Foo
和 Bar
。然而,无论我在哪里放置空格,Swift 都设法消除了以下表达式的歧义:
println(Dictionary<String, String>(0))
println(Dictionary < String, String > (0))
编译器如何管理这个?而且,更重要的是,Swift 语言规范中是否有任何位置。其中描述了规则。翻阅Swift书的Language Reference
部分,只找到这一段:
In certain constructs, operators with a leading
<
or>
may be split into two or more tokens. The remainder is treated the same way and may be split again. As a result, there is no need to use whitespace to disambiguate between the closing>
characters in constructs likeDictionary<String, Array<Int>>
. In this example, the closing>
characters are not treated as a single token that may then be misinterpreted as a bit shift>>
operator.
在此上下文中,certain constructs
指的是什么?实际语法只包含一个提到类型参数的产生式规则:
explicit-member-expression → postfix-expression
.
identifiergeneric-argument-clauseopt
任何解释或资源将不胜感激。
感谢@Martin R,我找到了编译器源代码的相关部分,其中包含解释它如何解决歧义的注释。
swift/ParseExpr.cpp
, line 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#中以类似的方式解决。