我有以下代码,假设来搜索数组并查看是否有任何内容与第二个参数匹配。
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的经验很少,所以,请详细解释发生了什么以及如何解决它!
答案 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)
首先,expr
是Boolean
。 Boolean
是true
或false
- 它不能是其他任何内容。另一方面,expr
来自“表达式”,我认为这是必须评估的一些公式。因此,expr
和Boolean
不太可能匹配,这是一些概念性问题正在发生的第一个线索。
现在,您将_ > 5
作为expr
参数传递,但_ > 5
既不是true
也不是false
。 10 > 5
为真,3 > 5
为假,但_ > 5
是函数,函数不是Boolean
。
让我们考虑下划线...... _ > 5
表示(x) => x > 5
。 _ > _
表示(x, y) => x > y
,依此类推。如果您不理解下划线,请不要使用它。请改用完整语法。你以后会得到理解,不需要用它减慢你的学习速度。
现在,由于另一个概念问题,我提出了这个问题:
_ => expr
这或多或少等同于z => expr
,即完全忽略它已收到的参数的函数。请注意,此处下划线的含义与上述不同。事实上,我曾在this answer计算了 11个不同含义的下划线。在你理解它们之前避免使用下划线的另一个原因。
因此,代码的问题在于:
Boolean
,您想要Function1[Any, Boolean]
。Boolean
的函数。现在,即使您修复了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