我最近在玩Play的JSON库,并注意到这不能编译:
val steps = Seq("a", "b", "c")
steps.foldLeft(__)((a, x) => a x)
经过一些修改和浏览源代码后,我找到了正确的表达式:
steps.foldLeft(JsPath())((a, x) => a x)
甚至:
steps.foldLeft(__())((a, x) => a x)
…虽然第二个看起来很混乱。
后来我发现了一个更有效、更简洁的表达方式:
JsPath(steps.toList map KeyPathNode)
但我不断回到原来的表达和玩弄它。我发现这是有效的:
steps.foldLeft(JsPath: JsPath)((a, x) => a x)
不知何故,这不是:
steps.foldLeft(__: JsPath)((a, x) => a x)
得到error: not found: value __
。但是,这是可行的:
steps.foldLeft((__): JsPath)((a, x) => a x)
steps.foldLeft({__}: JsPath)((a, x) => a x)
还:
steps.foldLeft(__.asInstanceOf[JsPath])((a, x) => a x)
为什么带__: JsPath
的表达式失败了?
…就在我准备提交这个问题之前,我发现了另一个有效的表达:
steps.foldLeft(__ : JsPath)((a, x) => a x)
似乎解析器将__:
解释为一个令牌。但它为什么会这样做呢?我认为下划线只是另一个有效的标识符字符。是否有一些特殊情况的解析规则在起作用?
下划线在标识符中是特殊的,因为它可以后跟操作符,包括:
:例如foo_+
是一个标识符,其中foo+
是两个令牌:foo
+
。
首先,标识符可以以字母开头,后面可以是任意的字母和数字序列。可以后跟下划线
_
字符和另一个由字母和数字或操作符字符组成的字符串。
注意,在第一个句子中,_
和$
被认为是大写字母。所以__:
是合法的标识符,但_:
不是。