SwiftMango
SwiftMango

Reputation: 15284

How to use placeholder syntax properly with map?

I am trying to use placeholder syntax for simple map:

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

I was expecting to have the same effect as:

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

It complains

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

I also tried:

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

Every one of them gives error. How to properly use this syntax in this case?


Edit

The link states that filter(_:Boolean) and filter (_ == true) should work, but my trials with specific typing does not work. This link also states that if (_) x else y should work, but in my case it does not. Need more explanation.


Edit 2

Tried:

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

It works. But my case:

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

Does not work.

Does this syntax only support such simple expressions?

Upvotes: 1

Views: 518

Answers (1)

Leo C
Leo C

Reputation: 22439

Re: your original question:

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

The _ placeholder used in such pattern represents positional parameters of an anonymous function, hence if (_ % 2 == 0) _ * 2 is equivalent to:

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

That explains the missing parameter error. The type mismatch error is due to missing else in the if statement, forcing the compiler to return a Unit:

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

Given that you need to specify the single input multiple times I'm not sure it'll work for you.

As you've already noticed, this placeholder syntax does have its limitation and should be treated as a convenient shortform for relatively simple cases. Like the if (_ % 2 == 0) 0 else 1) case, nesting _ within a map generally does not work well. For example:

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 ...

For more usage re: _, here is a SO link, and a Scala doc about commonly used symbols including _.

Upvotes: 3

Related Questions