下划线导致困难

时间:2012-07-13 02:50:12

标签: scala lambda functional-programming set scala-placeholder-syntax

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

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 个答案:

答案 0 :(得分: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)

答案 1 :(得分:4)

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

答案 2 :(得分: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)

首先,exprBooleanBooleantruefalse - 它不能是其他任何内容。另一方面,expr来自“表达式”,我认为这是必须评估的一些公式。因此,exprBoolean不太可能匹配,这是一些概念性问题正在发生的第一个线索。

现在,您将_ > 5作为expr参数传递,但_ > 5既不是true也不是false10 > 5为真,3 > 5为假,但_ > 5是函数,函数不是Boolean

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

现在,由于另一个概念问题,我提出了这个问题:

_ => expr

这或多或少等同于z => expr,即完全忽略它已收到的参数的函数。请注意,此处下划线的含义与上述不同。事实上,我曾在this answer计算了 11个不同含义的下划线。在你理解它们之前避免使用下划线的另一个原因。

因此,代码的问题在于:

  1. 您收到的是Boolean,您想要Function1[Any, Boolean]
  2. 在计算是否应该过滤时,您忽略了被过滤的元素(我假设因为这是唯一编译的语法,因为1)。
  3. 您正在传递预期为Boolean的函数。
  4. 现在,即使您修复了1和2,代码也无效,因为_ > 6不是有效Function1[Any, Boolean],因为Any未实现>。< / p>

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

    还有另外两个答案显示了如何正确地编写该方法,我将向他们推荐详细信息。我只是想解决一般性问题,看看我是否无法指导你将来避免这些问题。

答案 3 :(得分: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