Dmitry Smirnov
Dmitry Smirnov

Reputation: 472

Anonymous function in Scala, error depending on notation

I'm trying to diff two arrays. Specifically, I have one array with some strings, and another with indices that I want to clean from the first array. At first I tried to use anonymous function annotation with "_", but it didn't work, and I have a hard time understanding why. Here is an example:

val a1 = Array("word1","word2","word3")
val ind = Array(1,2)
val a2 = a1.zip(a1.indices)

val not_working = a2.filterNot( ind.contains(_._2) )

> console>:15: error: missing parameter type for expanded function
> ((x$1) => x$1._2)
>         a2.filterNot( ind.contains(_._2) )
>                                    ^ <console>:15: error: type mismatch; 
> found   : Boolean  required: ((String, Int)) => Boolean
>         a2.filterNot( ind.contains(_._2) )

My assumption was that _ corresponds to, for example, ("word1",0) or ("word2",1) tuples. But I don't understand the error, why does it get Boolean type here? I though it would get the second part of the tuple.

Just for the sake of it I tried to rewrite it more explicitly, and it worked. Here is an example that does what I expect, and to my naive eye it looks like the only thing I changed is notation:

val working = a2.filterNot( x => ind.contains(x._2) )

I'm having hard time understanding the difference between two examples. Why does the second one work?

Upvotes: 0

Views: 186

Answers (2)

Odomontois
Odomontois

Reputation: 16328

As it mentioned here and here and multiple other places

The placeholder syntax for anonymous functions replaces the smallest possible containing expression with a function.

So

a2.filterNot( ind.contains(_._2) )

will be desugared to

a2.filterNot( ind.contains(x => x._2) )

Upvotes: 0

Ryan
Ryan

Reputation: 7257

There are two errors stacked on top of each other:

val not_working = a2.filterNot( ind.contains(_._2) )

The first error is missing parameter type for expanded function. Essentially, the _ syntax can't be used everywhere and this is one of those cases. (In this case, it's because placeholder syntax can't be used within nested parentheses.

The second error is a result of the compiler not understanding that you were trying to use placeholder syntax, but it still knows that ind.contains returns a boolean. This is indicated in the error message: found: Boolean. The compiler thinks a Boolean value was passed to filterNot, but filterNot requires a function T => Boolean.

Once the syntax issue is fixed, the compiler correctly parses the expression and your example compiles.

Upvotes: 1

Related Questions