Function Scala:如何编写一个通用检查函数来计算任何返回布尔值的函数?

Function Scala:如何编写一个通用检查函数来计算任何返回布尔值的函数?,function,scala,generics,Function,Scala,Generics,我有点纠结于此:我需要一个可以接受任何函数的函数 类型fun(Any*):布尔作为参数,对函数求值并返回true或 错误,取决于功能评估的成功 本质上,我需要的是一个函数类型,它允许任何数量和任何类型的参数,但函数必须返回布尔值 这将允许我编写如下函数: def checkLenght(str : String, length : Int) : Boolean ={ if (str.lenght == length)} 或 我想,一个函数类型: type CheckFunction = (

我有点纠结于此:我需要一个可以接受任何函数的函数 类型fun(Any*):布尔作为参数,对函数求值并返回true或 错误,取决于功能评估的成功

本质上,我需要的是一个函数类型,它允许任何数量和任何类型的参数,但函数必须返回布尔值

这将允许我编写如下函数:

def checkLenght(str : String, length : Int) : Boolean ={
if (str.lenght == length)}

我想,一个函数类型:

  type CheckFunction = (Any*) => Boolean
may完成了这个技巧,但我很难编写通用的eval函数

有什么建议吗

多谢各位

解决方案:

该功能需要 1) 返回类型为布尔的另一个函数:“(func:=>Boolean)” 2) 返回类型布尔“:布尔” 3) 返回传递的函数参数的值:“=func”

总的来说,功能是:

   def eval(func : => Boolean) : Boolean = func
在Scala中,事情是多么简单,这让我再次感到惊讶

正如评论所指出的,这是一个相当不寻常的功能,没有明显的缺陷 感觉只需说说根本原因

动机:

关于潜在的动机有很多问题,所以这里有一个简短的 总结为什么需要这样一个功能

从本质上讲,有两个原因

第一个是关于将故障处理从函数本身移开 转换为处理程序函数。这保持了检查功能的纯度,甚至允许 重复使用一般检查

其次,它是关于“可插拔故障处理”的。这意味着,只有eval功能 说明是否发生了故障。如果出现故障,则通过接口调用处理程序。可以根据需要使用概要文件交换处理程序的实现

为什么?

交换配置文件意味着,我像往常一样对我的检查和功能进行编码,但通过切换 配置文件中,我切换处理程序,这意味着我可以选择全站、控制台打印输出、电子邮件警报、SNMP通知、推送消息。。。你说吧。为此,我需要将check函数与其求值和处理解耦。这就是这样一个看起来很奇怪的求值函数的动机

为了完整性,我已经实现了所有这些东西,但是我面临的限制是只处理琐碎的检查,例如检查(布尔*),这很简单,但我通常更喜欢编写一个函数来执行更复杂的检查


解决了的 通过返回传递函数的值来定义函数:

def eval(func : => Boolean) : Boolean = {func}

如果您的输入函数只有两个参数,就像您的两个示例一样,您可以编写一个半泛型函数take-takes-all函数,其中包含两个任意类型的参数:

def eval[A,B](func: (A,B) => Boolean, arg1: A, arg2: B) = {
    func(arg1, arg2)
}

def checkLength(str: String, length: Int) : Boolean = {
    str.length == length
}

eval(checkLength, "ham", 4)
res0: Boolean = false
但如果您想支持具有更多参数的函数,则必须为三个参数、四个参数等编写一个
eval
函数


也许有更好的方法可以处理所有情况?

如果您的输入函数只有两个参数,就像您的两个示例一样,您可以编写一个半泛型函数take-takes-all函数,其中包含两个任意类型的参数:

def eval[A,B](func: (A,B) => Boolean, arg1: A, arg2: B) = {
    func(arg1, arg2)
}

def checkLength(str: String, length: Int) : Boolean = {
    str.length == length
}

eval(checkLength, "ham", 4)
res0: Boolean = false
但如果您想支持具有更多参数的函数,则必须为三个参数、四个参数等编写一个
eval
函数


也许有更好的方法可以处理所有的情况?

我不能说我真的理解你想做你想做的事情的动机,但我想这不是重点。可能
eval
函数会在调用提供的函数之前检查某些内容,而不会在给定特定条件下调用其他函数(如快速失败)。也许您在调用函数后会进行一些后期检查,并根据其他内容更改结果。无论采用哪种方式,我认为您都可以通过如下代码实现类似于您所需的功能:

def main(args: Array[String]) {
  val str = "hello world"
  println(eval(checkLength(str, 3)))
  println(eval(intsEqual(1,1)))
}

def eval(func: => Boolean):Boolean = {
  //Do whetever you want before invoking func, maybe
  //not even invoke it if some other condition is present
  val fres = func

  //Maybe change something here before returning based on post conditions
  fres
}

def checkLength(s:String, len:Int) = s.length() == len
def intsEqual(a:Int, b:Int) = a == b
如果您确实希望
eval
函数能够支持采用任何类型的参数并返回
Boolean
的任何函数,则使用类似这样的按名称函数,然后利用按名称函数内的闭包将任何参数传递给您想要调用的实际函数。证明这一点的更好方法如下:

def checkMyString(str:String, len:Int) = {
  eval(str.length == len)
}
除非
eval
决定调用该检查,直到您将其扩展为真实形式,否则可能很难看到该检查
str.length==len
不会被调用:

def checkMyString(str:String, len:Int) = {
  def check = {
   str.length == len 
  }
  eval(check)
}
在这里,由于闭包,嵌套函数
check
可以访问
str
len
,这将允许您绕过
eval
必须能够使用返回
布尔值的任何参数调用函数的要求


这只是解决你问题的一种方法,考虑到你的需要,它可能并不合适,但我只是想把它扔出去。

我不能说我真的理解你想做你想做的事情的动机,但我想这与问题无关。可能
eval
函数会在调用提供的函数之前检查某些内容,而不会在给定特定条件下调用其他函数(如快速失败)。也许您在调用函数后会进行一些后期检查,并根据其他内容更改结果。无论采用哪种方式,我认为您都可以通过如下代码实现类似于您所需的功能:

def main(args: Array[String]) {
  val str = "hello world"
  println(eval(checkLength(str, 3)))
  println(eval(intsEqual(1,1)))
}

def eval(func: => Boolean):Boolean = {
  //Do whetever you want before invoking func, maybe
  //not even invoke it if some other condition is present
  val fres = func

  //Maybe change something here before returning based on post conditions
  fres
}

def checkLength(s:String, len:Int) = s.length() == len
def intsEqual(a:Int, b:Int) = a == b
如果您确实希望
eval
函数能够支持采用任何类型的参数并返回
Boolean
的任何函数,则使用类似这样的按名称函数,然后利用按名称函数内的闭包将任何参数传递给您想要调用的实际函数。证明这一点的更好方法如下:

def checkMyString(str:String, len:Int) = {
  eval(str.length == len)
}
除非
eval
决定调用该检查,直到您将其扩展为真实形式,否则可能很难看到该检查
str.length==len
不会被调用:

def checkMyString(str:String, len:Int) = {
  def check = {
   str.length == len 
  }
  eval(check)
}
这里是嵌套函数