说我有一个函数接受一个参数
def fun(x: Int) = x
基于此,我想生成一个具有相同调用约定的新函数,但是在委派给原始函数之前,将对其参数进行一些转换。为此,我可以
def wrap_fun(f: (Int) => Int) = (x: Int) => f(x * 2)
wrap_fun(fun)(2) // 4
除了对所有仅具有部分参数以共同应用转换的函数之外的其他函数,人们将如何做同样的事情?
def fun1(x: Int, y: Int) = x
def fun2(x: Int, foo: Map[Int,Str], bar: Seq[Seq[Int]]) = x
wrap_fun(fun1)(2, 4) // 4
wrap_fun(fun2)(2, Map(), Seq()) // 4
进行上述调用的
wrap_fun
定义将如何工作?
最佳答案
这可以通过使用shapeless's工具直接抽象出函数Arity来完成,
import shapeless._
import HList._
import Functions._
def wrap_fun[F, T <: HList, R](f : F)
(implicit
hl : FnHListerAux[F, (Int :: T) => R],
unhl : FnUnHListerAux[(Int :: T) => R, F]) =
((x : Int :: T) => f.hlisted(x.head*2 :: x.tail)).unhlisted
val f1 = wrap_fun(fun _)
val f2 = wrap_fun(fun1 _)
val f3 = wrap_fun(fun2 _)
REPL session 示例,
scala> f1(2)
res0: Int = 4
scala> f2(2, 4)
res1: Int = 4
scala> f3(2, Map(), Seq())
res2: Int = 4
请注意,您不能立即应用包装的函数(如在问题中),而不是通过分配的val(如上所述),因为包装的函数的显式参数列表将与
wrap_fun
的隐式参数列表混淆。我们最接近问题表格的方式是显式命名apply
方法,如下所示:scala> wrap_fun(fun _).apply(2)
res3: Int = 4
scala> wrap_fun(fun1 _).apply(2, 4)
res4: Int = 4
scala> wrap_fun(fun2 _).apply(2, Map(), Seq())
res5: Int = 4
在这里,对
apply
的明确提及从语法上标记了第一个应用程序(wrap_fun
及其隐式参数列表)与第二个应用程序(转换后的函数及其显式参数列表)。
关于scala - Scala函数转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10216278/