Torquémada
Torquémada

Reputation: 13

How do I use literal parameters with scala array collection?

I need help for this:

for example:

val myArray= Array(1, 2, 4, 5, -1, -7, 11, 29)

I understand this : myArray.exists( _ < 0 )

And also I can understand this: myArray.count(_ % 2 == 0)

but how I can write at REPL this:

myArray.forall( !xyz(_) )     xyz is this _ % 2 == 0 like above

I get this error:

"error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.unary_$bang.$percent(2).$eq$eq(0(x$2)))
              myArray.count( !_ % 2 ==0(_) )"

I have Eclipse 4.4. Luna.

Upvotes: 1

Views: 197

Answers (3)

zh2l4d7s
zh2l4d7s

Reputation: 97

Let's look at a variation on one of your examples:

myArray.count(!(_ % 2 == 0))

In this snippet, since the expression _ % 2 == 0 is enclosed in parentheses, the compiler parses it as an anonymous function by itself, rather than the entire !(_ % 2 == 0) as you might expect.

Treating what's in parentheses as a function, the compiler doesn't know what type to infer for the placeholder. You might think you could fix this by adding an annotation, giving

myArray.count(!((_: Int) % 2 == 0))

But this won't work either, because you are actually applying the unary ! operator to the anonymous function you've created!

To get around this, you could either simplify your predicate...

myArray.count(_ % 2 != 0)

...or eliminate the placeholder altogether.

myArray.count(n => !(n % 2 == 0))


EDIT: Although the suggestions above are probably the best ways to solve your problem, they do not directly address the error message you received when you entered the following (invalid) expression:

myArray.count(!_ % 2 == 0(_))

There are two problems here. The first is that your anonymous function _ % 2 == 0 is not wrapped in parentheses, leading the compiler to believe that the entire expression !_ % 2 == 0(_) is an anonymous function of two variables.

If we wrap our anonymous function in parentheses, we have

myArray.count(!(_ % 2 == 0)(_))

We've made progress, as the compiler is no longer looking for two parameters, but it cannot infer the type of the placeholder in the embedded function, so we must annotate it.

Finally, we have

myArray.count(!((_: Int) % 2 == 0)(_))

This works as expected. It's certainly not as elegant as the solutions presented above, but it does work.

Upvotes: 1

Sergey Lihoman
Sergey Lihoman

Reputation: 98

This is the same as in this question: Scala unexpectedly not being able to ascertain type for expanded function. Note: ! also a function

Upvotes: 0

uberwach
uberwach

Reputation: 1109

By using _ twice you are defining a function with two parameters - and a really weird one that is. The compiler tells you that it cannot make sense of your statement while it tries to derive the types of the two parameters - which is impossible.

In the cases before this was possible, for example in

myArray.exists(_ < 0) 

the compiler knows that exists on a Array[Int] expects a function Int to Bool. So the code is expanded to

myArray.exists((x : Int) => x < 0) 

In your case you should write:

myArray.forall( _ % 2 != 0)

An alternative would be

def xyz(n: Int) = n % 2 == 0
myArray.forall(!xyz(_))

A better error message would be something like "forall expects a function Int => Bool here". I think that this is not possible due to the existence of implicits in Scala. You can read more about this stuff in Chapter 8 of Martin Oderskys Scala book.

Upvotes: 0

Related Questions