是否可以编写 Scala 函数,使其获取任何函数并 returns 它的参数相反?
Can a Scala function be written such that it gets any function and returns it with its arguments reversed?
我知道这在 lisp 中是微不足道的,但 Scala 有一个强大的类型系统,这让我怀疑这样的功能是否可行。
如果不可能,那么宏呢? Scala 宏可以做到这一点吗?
PS:这是 Clojure 中的函数:
(fn [f](fn f* [& args] (apply f (reverse args))))
主要的困难是你必须找出带有反向参数的函数的类型,如果没有宏,就不可能以通用的方式做到这一点。
但是因为 Scala 只支持最多 22 个参数的函数,所以您可以为所有可能参数的函数编写或生成 23 个实现。下面是一个包含 3 个参数的函数的示例:
def reverse[A, B, C, R](f: (A, B, C) => R): (C, B, A) => R =
(c, b, a) => f(a, b, c)
虽然可以用通用的方式使用宏。最简单的解决方案可能是使用 shapeless 库,它是在内部使用宏实现的。这是无形的示例实现:
import shapeless._
import shapeless.ops.function._
import shapeless.ops.hlist._
def reverseArgs[Func, Args <: HList, Res, RevArgs <: HList](f: Func)(implicit
// Convert the function to a function from a single HList argument.
fnToProduct: FnToProduct.Aux[Func, Args => Res],
// Compute the type of the reversed arguments HList.
r1: Reverse.Aux[Args, RevArgs],
// Get the function to reverse the reversed arguments back.
reverse: Reverse.Aux[RevArgs, Args],
// Convert the function of a single HList argument to a normal function
fnFromProduct: FnFromProduct[RevArgs => Res]
): fnFromProduct.Out = {
fnFromProduct((args: RevArgs) => fnToProduct(f)(reverse(args)))
}
工作原理如下:
scala> val f = reverseArgs((i: Int, d: Double, s: String) => (i + d).toString + s)
f: (String, Double, Int) => String = shapeless.ops.FnFromProductInstances$$anon$$Lambda91/2014583896@4d7933e7
scala> f("a", 1.5, 2)
res1: String = 3.5a
我知道这在 lisp 中是微不足道的,但 Scala 有一个强大的类型系统,这让我怀疑这样的功能是否可行。 如果不可能,那么宏呢? Scala 宏可以做到这一点吗?
PS:这是 Clojure 中的函数:
(fn [f](fn f* [& args] (apply f (reverse args))))
主要的困难是你必须找出带有反向参数的函数的类型,如果没有宏,就不可能以通用的方式做到这一点。
但是因为 Scala 只支持最多 22 个参数的函数,所以您可以为所有可能参数的函数编写或生成 23 个实现。下面是一个包含 3 个参数的函数的示例:
def reverse[A, B, C, R](f: (A, B, C) => R): (C, B, A) => R =
(c, b, a) => f(a, b, c)
虽然可以用通用的方式使用宏。最简单的解决方案可能是使用 shapeless 库,它是在内部使用宏实现的。这是无形的示例实现:
import shapeless._
import shapeless.ops.function._
import shapeless.ops.hlist._
def reverseArgs[Func, Args <: HList, Res, RevArgs <: HList](f: Func)(implicit
// Convert the function to a function from a single HList argument.
fnToProduct: FnToProduct.Aux[Func, Args => Res],
// Compute the type of the reversed arguments HList.
r1: Reverse.Aux[Args, RevArgs],
// Get the function to reverse the reversed arguments back.
reverse: Reverse.Aux[RevArgs, Args],
// Convert the function of a single HList argument to a normal function
fnFromProduct: FnFromProduct[RevArgs => Res]
): fnFromProduct.Out = {
fnFromProduct((args: RevArgs) => fnToProduct(f)(reverse(args)))
}
工作原理如下:
scala> val f = reverseArgs((i: Int, d: Double, s: String) => (i + d).toString + s)
f: (String, Double, Int) => String = shapeless.ops.FnFromProductInstances$$anon$$Lambda91/2014583896@4d7933e7
scala> f("a", 1.5, 2)
res1: String = 3.5a