0

我有以下代码,它应该搜索一个数组并查看是否有任何内容与第二个参数匹配。

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)

但是当我调用它时:

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

我对函数式语言和 Scala 的经验很少,所以,请给我一个关于正在发生的事情以及如何解决它的彻底解释!

4

4 回答 4

6

问题是您评估表达式的时间之一。在您的通话中

check.filter(_ => expr)

您正在按传入的表达式check进行过滤。但是在您的调用中,您传递的是一个函数,而不是一个布尔值。

我认为你的意思是传递函数,然后在你的check调用中评估它。例如:

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

现在您可以按如下方式调用它:

any(Set(3, 4, 5, 6), (_:Int) > 5)
于 2012-07-13T03:22:15.870 回答
4
Set(3, 4, 5, 6).exists(_ > 5)
于 2012-07-13T03:07:22.873 回答
4

这段代码对 Scala 有一些误解。第一个需要解决的是:

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)

首先,expr是一个Boolean。ABoolean要么是要么true-false它不能是其他任何东西。另一方面,expr来自“表达式”,我认为这是必须评估的一些公式。因此,expr并且Boolean不太可能匹配,一些概念问题正在发生的第一个线索。

_ > 5现在,您作为expr参数传递,但_ > 5既不是true也不是false10 > 5会是真的,3 > 5会是假的,但是_ > 5是一个函数,而一个函数不是一个 Boolean.

让我们考虑下划线...的_ > 5意思(x) => x > 5_ > _的意思(x, y) => x > y,以此类推。如果你不太理解下划线,请不要使用它。请改用完整的语法。稍后您将获得理解,无需减慢您的学习速度。

现在,我提出这个是因为另一个概念问题,那就是:

_ => expr

这或多或少等价于z => expr,即完全忽略它收到的参数的函数。请注意,这里下划线的含义与上面不同。事实上,在这个答案中,我曾经计算过下划线的 11 种不同含义。在理解它们之前避免使用下划线的另一个原因。

因此,您的代码的问题在于:

  1. 您正在收到一个Boolean您想要的Function1[Any, Boolean].
  2. 在计算是否应该过滤它时,您忽略了被过滤的元素(我假设因为这是唯一编译的语法,因为 1)。
  3. 您正在传递一个预期为Boolean.

现在,即使您修复了 1 和 2 ,代码也不会工作,因为_ > 6它不是有效的Function1[Any, Boolean],因为Any没有实现>.

我怀疑您来自动态语言背景,并Any用作快速“后备”,不必告诉您正在处理的事物的类型。不要这样做——使用Any不会让事情变得更容易,只会让事情变得更难。

还有其他两个答案显示了如何正确编写该方法,我将把细节交给他们。我只是想解决一般问题,看看我是否不能指导您将来避免此类问题。

于 2012-07-13T16:08:22.480 回答
3

除了@RayToals 回答:

如果您创建多个参数列表,则可以使用 Scalas 类型推断:

def any[T](check: Set[T])(test: T => Boolean): Boolean = {
  val checked = check.filter(test)
  checked.nonEmpty
}

scala> any(Set(3,4,5,6))(_>5)
res6: Boolean = true

scala> any(Set(3,4,5,6))(_>6)
res7: Boolean = false

注意:不要使用 return 语句(特别是不要明确地返回 true 和 false)——大多数时候它们是不需要的。此外,var当您不确定是否需要它时,不要使用它。最后,可以将整个方法写在一个表达式中:

def any[T](check: Set[T])(test: T => Boolean): Boolean =
  check.filter(test).nonEmpty
于 2012-07-13T07:58:48.323 回答