以任意数量的参数作为参数的函数 [英] Function with any number of arguments as parameter

查看:163
本文介绍了以任意数量的参数作为参数的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有方法eval它需要函数和参数列表,目前我正在为每个可能的函数写作案例。

I have method eval which takes List of Function and arguments, currently I am writing case for every possible function. How can I write it more generic?

implicit class Expression(p: Product) {
  def eval = p.productIterator.toList match {
    case (f: ((Any) => Any)) :: p1 :: Nil => f(p1)
    case (f: ((Any, Any) => Any)) :: p1 :: p2 :: Nil => f(p1, p2)
    case (f: ((Any, Any, Any) => Any)) :: p1 :: p2 :: p3 :: Nil => f(p1, p2, p3)
  }
}
def print = (x: Any) => println(">> " + x)
def add = (x: Any, y: Any) => x.asInstanceOf[Int] + y.asInstanceOf[Int]
(print, "test").eval
(add, 2, 3).eval


推荐答案

你可以使用无形式来写这样的东西,它具有类型安全的优点, (比较在 Expression.eval 中使用任意)。

You could write something like this using shapeless, which has the benefit that it is type safe and checked at compile time (compared with using Any in your Expression.eval).

import shapeless._
import ops.hlist._
import syntax.std.function._
import ops.function._

def eval[P <: Product, G <: HList, F, L <: HList, R](
  p: P
)(implicit 
  gen: Generic.Aux[P, G], 
  ihc: IsHCons.Aux[G, F, L], 
  ftp: FnToProduct.Aux[F, L => R]
) = { 
  val l = gen.to(p)
  val (func, args) = (l.head, l.tail)
  func.toProduct(args)
}

您可以用作:

Which you could use as :

def add(a: Int, b: Int) = a + b
val stringLength: String => Int = _.length

eval((add _, 1, 2))             // Int = 3
eval((stringLength, "foobar"))  // Int = 6
eval((stringLength, 4))         // does not compile

您也可以将它与如果一个case类遵循相同的格式(首先是一个函数,然后是该函数的正确参数):

You can also use it with a case class if it follows the same format (first a function then the right arguments for that function) :

case class Operation(f: (Int, Int) => Int, a: Int, b: Int)
eval(Operation(_ + _, 1, 2))    // Int = 3
eval(Operation(_ * _, 1, 2))    // Int = 2

这篇关于以任意数量的参数作为参数的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆