Scala编译器说"错误:预期的标识符,但找到整数文字." for()not {}

Jac*_*ski 12 scala

为什么Scala 2.11.0-M3编译器在使用error: identifier expected but integer literal found.圆括号时会给我,()而用大括号编译好{}

$ scala
Welcome to Scala version 2.11.0-M3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_21).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val s = "this is a string"
s: String = this is a string

scala> s.toList map (c:Char => 1)
<console>:1: error: identifier expected but integer literal found.
       s.toList map (c:Char => 1)
                               ^

scala> s.toList map {c:Char => 1}
res7: List[Int] = List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
Run Code Online (Sandbox Code Playgroud)

不知何故,当匿名函数的左侧位于另一对圆括号内时,它也可以用圆括号编译.为什么?

scala> s.toList map ((c:Char) => 1)
res8: List[Int] = List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
Run Code Online (Sandbox Code Playgroud)

som*_*ytt 8

当你写作

{i:Int => 2*i}

大括号是一个块,里面的东西是块的结果表达式.

语法是ResultExpr.请注意,在param名称之后允许使用类型,如上所述.

这与Expr不同.

以下是差异的示例:

scala> val is = List(1,2,3)
is: List[Int] = List(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

块中的第一个语句具有函数文字,如果我们指定类型,则需要parens.最后一个语句是块的结果表达式,不需要parens:

scala> is map { val f = (i: Int) => 2*i; i: Int => 2*f(i) }
res0: List[Int] = List(4, 8, 12)
Run Code Online (Sandbox Code Playgroud)

有时您不需要指定类型,因为它是从期望的类型推断出来的,并且在Expr中没有类型,您可以省略parens:

scala> is map { val f: Int=>Int = i => 2*i; i: Int => 2*f(i) }
Run Code Online (Sandbox Code Playgroud)

这些产品中的绑定(在规范中)是普通的parens中的params列表,可能有类型.有多个param,你必须提供parens:

scala> is reduce { val f = (i:Int,j:Int) => i+j; (i:Int,j:Int) => 2*f(i,j) }
res2: Int = 18
Run Code Online (Sandbox Code Playgroud)

有时您会看到一大块代码作为函数的参数.这是一个大函数文字作为块的结果表达式,这就是为什么你看到参数坐在前面,没有parens或括号:

scala> is map { i =>  val j = 2 * i; /* lots of LOC */ ; j }
res7: List[Int] = List(2, 4, 6)
Run Code Online (Sandbox Code Playgroud)

这与下面的代码不同,后者是最后一行函数文字的多行代码块.函数只返回j,或2:

scala> is map { val j = 2; /* lots of LOC */ ; _ => j }
res8: List[Int] = List(2, 2, 2)
Run Code Online (Sandbox Code Playgroud)

所以我们知道你不能写下面的内容:

scala> is map (is: Int => 2)
<console>:1: error: identifier expected but integer literal found.
       is map (is: Int => 2)
                          ^
Run Code Online (Sandbox Code Playgroud)

在这种情况下,哪种标识符有意义?怎么样:

scala> is map (is: Int => Int)
Run Code Online (Sandbox Code Playgroud)

产生令人愉快的结果(剧透警报):

java.lang.IndexOutOfBoundsException: 3
Run Code Online (Sandbox Code Playgroud)

这有效:

scala> val js = List(0,1,2)
js: List[Int] = List(0, 1, 2)

scala> js map (js: Int => Int)
res0: List[Int] = List(0, 1, 2)
Run Code Online (Sandbox Code Playgroud)

js中括号只是一个值,显然,不设置了一个param,类型是类型归属.该值可以是修复后的表达式,因此可以(或者更确切地说,使用有关修复后操作符语法的功能警告进行编译):

scala> js map (js init: Int => Int)
warning: there were 1 feature warning(s); re-run with -feature for details
java.lang.IndexOutOfBoundsException: 2
Run Code Online (Sandbox Code Playgroud)

在这个答案的更多解释:

/sf/answers/971172961/

认为parens和花括号在某种程度上是可交换的,会引起一种混乱.但是我发现它看起来很明显BlockExprs,就像它们一样.然后更容易记住,例如,当你在函数应用程序中使用大括号时,没有魔法:你只是提供了一个.

块是一组副作用语句,后跟结果语句.对于功能程序员来说,这可能是显而易见的.但它澄清了你的大括号中的最后一件事是ResultExpr.

(脚注:课堂主体的大括号当然不同.)