通过列表作为单个功能参数

Max*_*wer 5 scala

我有一个函数def f(a: Int, b: Int, c: Int, d: Int, ...),我想提供一个连续整数列表作为参数(在单元测试中)。

有没有一种整齐的供应(1 to N).toList方式f?由于该功能是不是def f(x: Int*),我不能简单地用list: _*list整数列表。

Kol*_*mar 2

我不认为你可以在标准 Scala 中以类型安全的方式做到这一点,但可以使用Shapeless库来做到这一点。即使您不在项目中使用此库,您也只能在测试范围内依赖它。

这是代码示例:

import shapeless._
import shapeless.ops.function._
import shapeless.ops.traversable._

def applyToList[F, HL <: HList, R](f: F)(args: List[Any])(implicit
  // convert `(T1, T2, ...) => R` to a function from a single HList argument `HL => R`
  fnToProduct: FnToProduct.Aux[F, HL => R],  
  // convert the argument list to the HList, expected by the converted function
  toHList: FromTraversable[HL]
): R = {
  toHList(args) match {
    case Some(hargs) => fnToProduct(f)(hargs)
    case None => sys.error("argument list not applicable to function")
  }
}
Run Code Online (Sandbox Code Playgroud)

使用它就像这样简单:

def f(a: Int, b: Int, c: Int, d: Int): Any = ???
applyToList(f _)(List(1, 2, 3, 4))
Run Code Online (Sandbox Code Playgroud)

但请注意需要显式 eta-conversion f _,因为 Scala 编译器并不真正知道这F是一个函数。

您可以将定义更改为 return Option[R],因为在编译时不可能知道提供的内容List是否适合该函数。例如,参数列表可能具有不匹配数量的元素。但如果这是用于单元测试,您也可以抛出异常。