Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala anonymous functions question

I am trying to filter a map from strings to ints in scala and I am running into a weird issue.

If I put the following into REPL:

scala> val myMap = Map("a" -> 1, "b" -> 2, "c" -> 3)
myMap: scala.collection.immutable.Map[java.lang.String,Int] = 
| Map(a -> 1, b -> 2, c -> 3)

It's ok so far, and this works...

scala> myMap.filter(_._2 > 1)
res9: scala.collection.immutable.Map[java.lang.String,Int] = Map(b -> 2, c -> 3)

but this fails...

scala> myMap.filter((k:java.lang.String, v:Int) => v > 1)
<console>:9: error: type mismatch;
 found   : (java.lang.String, Int) => Boolean
 required: ((java.lang.String, Int)) => Boolean
   myMap.filter((k:java.lang.String, v:Int) => v > 1)

My question is what is going on with the error message and the extra pair of parentheses? If I try putting in an extra set of parentheses I get error: not a legal formal parameter.

like image 396
chuck taylor Avatar asked Nov 30 '22 04:11

chuck taylor


2 Answers

filter accepts a function that accepts only one parameter. In your expression, the expression accepts two parameters. However, the element happen to be a pair, so you may think you can give two parameters. The correct way of putting it would be something like:

myMap.filter (p => p._2 > 1)

That is, I receive a pair, p, and its second element must be greater than 1.

like image 44
Diego Sevilla Avatar answered Dec 05 '22 11:12

Diego Sevilla


myMap.filter expects a function of type Tuple2[String, Int] => Boolean, which is equivalent to ((String, Int)) => Boolean. You're passing it a function of type (String, Int) => Boolean; that is, a function that takes two arguments rather than a single Tuple2.

Two ways to get it to work:

 myMap.filter { case (k, v) => v > 1 }

and

 myMap.filter(Function.tupled((k, v) => v > 1))

The first works by pattern matching, and the second by converting the function (String, Int) => Boolean to ((String, Int)) => Boolean.

By the way, there has been discussion about unifying tuples and function argument lists. Maybe in a future version of Scala, all functions will take a single parameter (which might be a tuple).

like image 136
Kipton Barros Avatar answered Dec 05 '22 10:12

Kipton Barros