4

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.

2 Answers 2

16

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

Sign up to request clarification or add additional context in comments.

7 Comments

Agreed. Function.tupled is explicit while the pattern match seems more like a trick.
Sorry if this is a dumb question, but why does the pattern matching with case work with curly braces {} but not parentheses?
Not a dumb question at all. I don't know a better answer than "that's what the Scala Language Spec says". You might be interested in this discussion of the difference between () and {}: stackoverflow.com/questions/4386127/…
@Kipton Is Function.tupled deprecated? It had been deprecated, but that had been reversed because Function.tupled is friendlier to type inference.
@Daniel, it's deprecated according to the source code linked from these nightly docs: scala-lang.org/archives/downloads/distrib/files/nightly/docs/…
|
6

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.