【问题标题】:How can I make function for unspecified number of arguments function In Scala?如何在Scala中为未指定数量的参数函数创建函数?
【发布时间】:2016-05-04 18:36:16
【问题描述】:

我想为未指定数量的函数参数创建一些函数

例如

scala> def test(fx: (String*) => Boolean, arg: String*): Boolean = fx(arg: _*)
test: (fx: String* => Boolean, arg: String*)Boolean

scala> def AA(arg1: String, arg2: String) :Boolean = {
       println ("Arg1 : " + arg1 + " Arg2 : " + arg2)
       true}
AA: (arg1: String, arg2: String)Boolean

scala> test(AA,"ASDF","BBBB")
<console>:10: error: type mismatch;
 found   : (String, String) => Boolean
 required: String* => Boolean
            test(AA,"ASDF","BBBB")
                  ^

我该如何解决这个问题??

【问题讨论】:

  • 有一些方法可以解决这个问题,但您确实意识到,当您传入 args 不同数量的值时,您可能会在 runtime 遇到错误987654323@ 期望?你可以吗?
  • 另外,您能否更具体地说明您想要实现的目标?就目前而言,您的 test 方法只是调用传递的函数,因此很难猜测为什么您不能直接调用该函数(因此很难提出任何可能更明智的替代方案)

标签: scala


【解决方案1】:

这可以使用 shapeless 和 ProductArgs 以及类似于我的 answer 的另一个问题来完成。

import shapeless.{HList, ProductArgs}
import shapeless.ops.hlist.IsHCons
import shapeless.ops.function.FnToProduct
import shapeless.syntax.std.function._

object test extends ProductArgs {
  def applyProduct[L <: HList, NarrowArgs <: HList, Args <: HList, F, R](
    l: L
  )(implicit 
    ihc: IsHCons.Aux[L, F, NarrowArgs],
    ftp: FnToProduct.Aux[F, Args => R],
    ev: NarrowArgs <:< Args
  ): R = {
    val (func, args) = (l.head, l.tail)
    func.toProduct(args)
  }
}

你可以用作:

def aa(s1: String) = s1.length
def bb(s1: String, s2: String) = s1 * s2.length

test(aa _, "foo")         // Int = 3
test(bb _, "foo", "bar")  // String = foofoofoo
// test(aa _, "foo", "bar") doesn't compile

ProductArgs 转换或test(aa _, "foo")(实际上是test.apply(aa _, "foo"))扩展为test.applyProduct((aa _) :: "foo" :: HNil)。在applyProduct 中,我们检查HList 是否由函数和有效参数组成。


我们不应该需要NarrowArgs &lt;:&lt; Args,但ProductArgs 的结果似乎与SingletonProductArgs 相同。

【讨论】:

  • 这很好,但它明确假设在调用 test 时完全知道函数 arity(实际上,甚至是确切的签名)(或者 - 诚然 - 我们可以传递无形类型类实例以及函数,以使调用编译)。如果是这种情况,那么test 除了直接调用所述函数(或将 thunk 传递给test 之外,还能带来什么)。我认为如果 OP 准确地解释他的用例是什么,那会更有成效。
  • @RégisJean-Gilles 你是对的,test 实际上并不是很有用。
【解决方案2】:

这是因为AA不接受可变数量的参数,改成:

def AA(args: String*) :Boolean

【讨论】:

  • 谢谢。但我想获得所有功能而不参考任何数量的参数。如果我有 2 个像 def AA (arg: String) = println(arg)def BB(arg1: String, arg2: String) = println(arg1 + arg2) 这样的函数,我想将它作为参数传递给 test 函数。 test(AA,"HELLO")test(BB,"HELLO","WORLD") 有可能吗??
  • 我不确定这是否可能。
猜你喜欢
  • 1970-01-01
  • 2021-09-08
  • 2021-06-15
  • 2014-03-31
  • 1970-01-01
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多