Underscore Causing Difficulties

I have the following code, which is supposed to search through an array and see if the anything matches the second argument.

def any(check: Set[Any], expr: Boolean): Boolean = {
  var checked = check.filter(_ => expr)
  if (checked == Set())
    return false
  else
    return true
}

It is supposed to be called like this: any(Set(3, 4, 5, 6), _ > 5)

But when I call it:

error: missing parameter type for expanded function ((x$1) => x$1.$greater(5))

I have very little experience with functional languages, and Scala, so, please give me a thorough explanation of what is going on and how to fix it!


The issue is one of the time in which you evaluate expressions. In your call

check.filter(_ => expr)

you are filtering check by the value of an expression passed in. But in your call, you are passing a function, not a boolean.

What you mean to do, I think, is to pass the function, then evaluate it in your check call. For example:

def any[T](check: Set[T], test: T => Boolean): Boolean = {
  var checked = check.filter(test)
  if (checked == Set())
    return false
  else
    return true
}

Now you can call this as follows:

any(Set(3, 4, 5, 6), (_:Int) > 5)

Set(3, 4, 5, 6).exists(_ > 5)

There are some misconceptions about Scala in this code. The first one that needs to be addressed is this:

def any(check: Set[Any], expr: Boolean): Boolean = {
  var checked = check.filter(_ => expr)
  if (checked == Set())
    return false
  else
    return true
}

any(Set(3, 4, 5, 6), _ > 5)

First, expr is a Boolean . A Boolean is either true or false -- it can't be anything else. On the other hand, expr comes from "expression", which I think of as some formula that must be evaluated. So, expr and Boolean are unlikely matches, the first clue that some conceptual problem is afoot.

Now, you pass _ > 5 as expr parameter, but _ > 5 is neither true nor false . 10 > 5 would be true, 3 > 5 would be false, but _ > 5 is a function, and a function is not a Boolean .

Let's consider the underscore... _ > 5 means (x) => x > 5 . _ > _ means (x, y) => x > y , and so on. If you don't understand underscore well, don't use it. Use the full syntax instead. You'll gain understanding later, no need to slow down your learning with it.

Now, I bring that up because of the other conceptual problem, which is this:

_ => expr

This is more or less equivalent to z => expr , that is, a function which completely ignores the parameter it has received. Notice that the meaning of underscore here is different than above. In fact, I've once counted 11 different meanings for underscore , in this answer. One more reason to avoid using underscores until you understand them.

So, the problem with your code is that:

  • You are receiving a Boolean where you wanted a Function1[Any, Boolean] .
  • You are ignoring the element being filtered when computing whether it should be filtered or not (I assume because that's the only syntax that compiled, because of 1).
  • You are passing a function where it is expected a Boolean .
  • Now, the code won't work even if you fix 1 and 2 because _ > 6 is not a valid Function1[Any, Boolean] , since Any does not implement > .

    I suspect you come from a dynamic language background, and use Any as a quick "fallback" to not having to tell what is the type of the things you are handling. Don't do it -- using Any doesn't make things easier, it makes things harder.

    There are two other answers that show how to write that method correctly, and I'll defer to them the particulars. I only wanted to address the general problem, and see if I can't guide you into avoiding such problems in the future.

    链接地址: http://www.djcxy.com/p/72838.html

    上一篇: 这些scala方法中的下划线使用之间的区别

    下一篇: 下划线造成困难