如何正确使用占位符语法与地图?

时间:2018-06-14 14:25:14

标签: scala

我正在尝试使用占位符语法来处理简单的地图:

Array(1,2,3).map(if(_ % 2 == 0) _ * 2)

我希望能产生与以下相同的效果:

Array(1,2,3).map(i=>if (i%2==0) i * 2)

抱怨

error: type mismatch;
 found   : Unit
 required: Int => ?

我也尝试过:

Array(1,2,3).map(if(_ % 2 == 0) _ * 2 else _)                    //with else
Array(1,2,3).map(if((_:Int) % 2 == 0) (_:Int) * 2 else (_:Int))  //All typed
Array(1,2,3).map(if((_:Int) % 2 == 0) 0 else 1)                  //Typed and specific return Int

他们每个人都会犯错误。在这种情况下如何正确使用这种语法?

修改

该链接指出filter(_:Boolean)filter (_ == true)应该有效,但我的特定类型的试验不起作用。此link还指出if (_) x else y应该有效,但在我的情况下则不然。需要更多解释。

修改2

尝试:

Array(true,false).map(if(_) 0 else 1)

有效。但我的情况是:

Array(1,2,3).map(if((_) % 2 == 0) 0 else 1)

不起作用。

这种语法是否只支持这种简单的表达式?

1 个答案:

答案 0 :(得分:3)

回复:你原来的问题:

Array(1, 2, 3).map(if (_ % 2 == 0) _ * 2)
// error: missing parameter type for expanded function ...
// error: type mismatch ...

此类模式中使用的_占位符表示匿名函数的位置参数,因此if (_ % 2 == 0) _ * 2等同于:

if (x => x % 2 == 0) y => y * 2

这解释了missing parameter错误。 type mismatch错误是由于else语句中缺少if而导致编译器返回Unit

Array(1, 2, 3).map(i => if (i % 2 == 0) i * 2 else i)
// res1: Array[Int] = Array(1, 4, 3

鉴于您需要多次指定单个输入,我不确定它是否适合您。

正如您已经注意到的,这个占位符语法确实有其局限性,对于相对简单的情况应该被视为一种方便的缩写。与if (_ % 2 == 0) 0 else 1)案例一样,在_内嵌套map通常效果不佳。例如:

List("a", "b", "c").map(_ * 3)
// res2: List[String] = List(aaa, bbb, ccc)

List("a", "b", "c").map((_ + " ") * 3)
// error: missing parameter type for expanded function ...

有关更多用法的信息:_,此处为SO linkScala doc有关常用符号,包括_