【问题标题】:Underscore Causing Difficulties下划线导致困难
【发布时间】:2012-07-12 21:23:37
【问题描述】:

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

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 的经验很少,所以,请给我一个详尽的解释,说明发生了什么以及如何解决它!

【问题讨论】:

  • 糟糕,这是最后一分钟的编辑,我也遇到了布尔问题。
  • Scala 的类型系统非常强大,不幸的是,这让初学者有时很难理解,因为错误消息通常没有帮助。

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


【解决方案1】:

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

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)

【讨论】:

    【解决方案2】:
    Set(3, 4, 5, 6).exists(_ > 5)
    

    【讨论】:

      【解决方案3】:

      在这段代码中有一些关于 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)
      

      首先,exprBooleanBoolean 要么是 true 要么是 false - 它不能是其他任何东西。另一方面,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

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

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

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

      【讨论】:

      • 非常感谢,很好的回答,您对动态语言的看法是正确的,我来自 Ruby 和 Python :)
      【解决方案4】:

      除了@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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-03
        • 1970-01-01
        • 2020-12-11
        • 1970-01-01
        • 2023-03-20
        • 1970-01-01
        相关资源
        最近更新 更多