Bre*_*ust 5 parameters dsl scala function-calls
有没有办法调用一个带有单个参数的Scala函数,给定一个数组(类似于ECMAScript 6中的JavaScript Spreads)?
ys = [10.0, 2.72, -3.14]
f(x, ...ys);
Run Code Online (Sandbox Code Playgroud)
最干净的语法是:
f(1, ys)
Run Code Online (Sandbox Code Playgroud)
但这似乎不可能.甚至f(1, ys:_*)不起作用(也没有f(ys:_*),因为编译器报告的参数太少 - 只填充第一个参数).
例:
def f (a:Int, b:Float, c:Float, d:Float): String
val x = 1
val ys = List(10.0, 2.72, -3.14) // note: non-Objects
val result = f(x, ys) // intuitive, but doesn't work
Run Code Online (Sandbox Code Playgroud)
用例:将测试数据(来自集合)注入到接受单个参数的现有方法中.由于这些是测试用例,如果ys中的#params不匹配并且提供运行时错误或不正确的结果,那就很好了.
问题是Scala是否允许一个干净的语法来调用一个带有单个参数的函数,给定一组参数 - 而不是它是否是一个好的设计(尽管意见肯定是受欢迎的).
将列表作为元组传递并不容易,因为类型不太匹配(稍后会详细介绍)。只要有足够的鞋拔和润滑,任何东西都适合:
"My hack" should {
"allow a function to be called with Lists" in {
def function(bar:String, baz:String)= bar+baz
//turn the function into something that accepts a tuple
val functionT = function _
val functionTT = functionT.tupled
val arguments = List("bar", "baz")
//Give the compiler a way to try and turn a list into a tuple of the size you need
implicit def listToTuple(args:List[String]) = args match {
case List(a, b) => (a, b)
case _ => throw IllegalArgumentException("Trying to pass off %s as a pair".format(args))
}
//Shove it in and hope for the best at runtime
val applied = functionTT(arguments)
applied === "barbaz"
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过将其他参数添加到列表中或通过 Schönfinkeling 将参数分配到两个不同的组中来扩展此方法。我不会走那条路。
从我的评论中,您可能已经注意到,我不喜欢导致出现此问题的设计。我展示的代码本质上是将函数包装在外观中的代码。为什么不好好做呢?
查看 Spray,您可能会发现他们的完整方法隐式接受大量不同的参数。他们为此使用的巧妙技巧被命名为“磁铁图案”。您可以做同样的事情,并为您选择接受的不同元组引入隐式转换到您的磁铁。
| 归档时间: |
|
| 查看次数: |
4159 次 |
| 最近记录: |