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

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

问题描述

有没有什么方法可以调用带有单个参数的 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 是否允许使用干净的语法来调用接受单个参数的函数,给定参数集合——而不是它是否是一个好的设计(尽管意见当然是受欢迎的).

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

您可以通过将附加参数添加到列表中,或通过 Schönfinkeling 在两个不同组中的参数来扩展此方法.我不会走那条路.

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 中的“传播"参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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