匿名类函数的占位符语法

2018-02-19  本文已影响18人  Azur_wxj

匿名类函数的占位符语法

考虑下面的代码:

val numSeq=Array(3.1415,2.71828,9.8)

下面想用foreach方法输出它们的整数,如果用占位符语法,比如下面这样:

scala> numSeq foreach (println(_.toInt))

<console>:13: error: missing parameter type for 
  expanded function ((x$1: <error>) => x$1.toInt)
     numSeq.foreach(println(_.toInt))
                            ^

看起来,我们本意是将println(_.toInt)解释为x=>println(x.toInt),但是编译器却理解为x=>x.toInt,自然不对。这是因为,添加了一对括号后((_.toInt))就形成了新的词法作用域,因此println(_.toInt)会被解读为println(x=>x.toInt)
(参考:Scala placeholder syntax for anonymous function

既然如此,不妨去掉括号看看:

scala> numSeq foreach (println_.toInt)  没有加空格
<console>:13: error: not found: value println_
       numSeq foreach (println_.toInt)
                       ^

很容易错的地方,就是在函数名和下划线之间不加空格,这就会将println_看做一个标识符。

scala> numSeq foreach (println _.toInt)
<console>:1: error: ')' expected but '.' found.
       numSeq foreach (println _.toInt)

注意,scala里面,使用method()可以简写为method,但是method(x)不能省略括号method x (错误)。(这是Groovy的语法,搞混了_(:зゝ∠)_)
有一个特殊的下划线用法,也就是说,指代整个参数列表,就可以写成method _,所以,println _.toInt事实上是println _,显然后跟.toInt就不合理了,因为这就变成( x=>println(x) ).toInx,语法错误。

那么该怎么做呢?注意到在scala里,如果对象obj调用一个方法method,而该方法只接受一个参数x,那么obj.method(x)可以简写为obj method xobj method (x),看起来method就不是一个方法名而是一个中缀操作符,换言之

scala> numSeq foreach (Console println _.toInt)
3
2
9

此时,编译器明确是三部分,所以_.toInt就被视为一个整体,从而Console println _.toInt就被翻译成我们需要的x=>Console.println(x,toInt)

现在想要将numSeq升序排序:

scala> numSeq.sortWith{ _.compareTo(_)<0 }
res93: Array[Double] = Array(2.71828, 3.1415, 9.8)

_.compareTo(_)<0实际上是(x,y) => { x.compareTo(y)<0 }

更多参考:scala 下划线解析报错: missing parameter type for expanded func

下划线文法的就近展开原则原则:

Underscores extend outwards to the closest closing Expr : top-level expressions or expressions in parentheses

匿名函数简写注意事项:
所以当匿名函数有多个括号嵌套的时候,不要使用_的简写方式 ,而应该用普通匿名函数的书写方式。比如 (x:Int,y:Int)=> (x*2)+f(y+2)

_本身构不成一个表达式:expressions,所以如下是允许的scala> List(1,2,3,4).foreach(print(_)) => List(1,2,3,4).foreach(print _) => List(1,2,3,4).foreach(print) => List(1,2,3,4) foreach print => List(1,2,3,4) foreach print _

上一篇 下一篇

猜你喜欢

热点阅读