Scala中的"Spread"参数? [英] 'Spread' parameters in Scala?

查看:102
本文介绍了Scala中的"Spread"参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以通过给定数组调用采用单个参数的Scala函数(类似于JavaScript 价差在ECMAScript 6中)?

Is there any way to call a Scala function that takes individual parameters, given an array (similar to JavaScript Spreads in ECMAScript 6)?

ys = [10.0, 2.72, -3.14]
f(x, ...ys);

最干净的语法是:

f(1, ys)

,但这似乎是不可能的.甚至f(1, ys:_*)都不起作用(f(ys:_*)也不起作用,因为编译器报告的参数太少-仅填充第一个参数).

but that does not appear to be possible. Even f(1, ys:_*) does not work (and neither does f(ys:_*), as the compiler reports too few parameters - only the first one is filled).

示例:

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

用例:将测试数据(来自集合)注入接受单个参数的现有方法中.由于这些都是测试用例,因此如果ys中的#params不匹配并且给出运行时错误或错误结果,就可以了.

Use Case: injecting test data (from collections) into existing methods that accept individual parameters. As these are test cases, it's quite alright if the #params in ys doesn't match up and that gives either a runtime error or incorrect result.

问题是,在给定参数集合的情况下,Scala是否允许使用干净的语法来调用带有单个参数的函数,而不是它是否是一个好的 design (尽管当然欢迎意见).

The question is whether Scala allows a clean syntax for calling a function that takes individual parameters, given a collection of parameters -- not whether it is a good design (although opinions are certainly welcome).

推荐答案

将列表作为元组传递是不容易的,因为类型之间的匹配度不高(稍后会对此进行详细介绍).借助足够的鞋拔和润滑,一切都适合:

Passing off a list as a tuple is not easy, because the types don't match very well (more on this later). With enough shoehorning and lubricating anything fits though:

"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"
  }
}

您可以通过将其他参数添加到列表中,或者通过将参数分成两个不同的组来扩展此方法.我不会那样走的.

You can extend this approach by adding the additional arguments to the list, or by Schönfinkeling the arguments in two different groups. I wouldn't go that way.

根据我的评论,您可能已经注意到,我不喜欢导致该问题弹出的设计.我展示的代码本质上是将函数包装在外观中的代码.为什么不正确地做呢?

From my remarks you might have noticed that I don't like the design that causes this question to pop up. The code I showed is essentially code that is wrapping the function in a facade anyway. Why not do it properly?

查看Spray,您可能会发现它们的完整方法隐式接受了许多不同的参数.他们为此使用的巧妙技巧将其命名为磁铁模式.您可以做同样的事情,并为您选择接受的不同元组对磁铁进行隐式转换.

Looking at Spray you might see that their complete method accepts a ton of different parameters implicitly. The nifty trick they've used for this they've named the Magnet Pattern. You could do the same thing and introduce implicit conversions to your magnet for different tuples you choose to accept.

这篇关于Scala中的"Spread"参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆