scala - Scala函数转换

标签 scala functional-programming closures

说我有一个函数接受一个参数

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/

相关文章:

javascript - Pointfree 在 Ramda 中通过对象中的键将数组连接到字符串

swift - Swift 编译器的错误消息是什么?

scala - 在父类(super class)中实现宏并在子类中扩展它

scala - Scala 注解实际上是什么?

java - Scala 中的多个构造函数应该调用不同的 super 方法

javascript - Ramda如何将参数传递给高阶函数?

scala - 是否有任何记录在案的函数式编程反模式?

scala:将错误添加到错误列表的惯用和功能方式

closures - 将参数传递给javascript中的闭包函数

javascript 循环中的闭包