Ben
Ben

Reputation: 105

How can I make function for unspecified number of arguments function In Scala?

I want to make some function for unspecified number of arguments of function

for example

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")
                  ^

How can I solve this problem??

Upvotes: 1

Views: 572

Answers (2)

Peter Neyens
Peter Neyens

Reputation: 9820

This could be done using shapeless with ProductArgs and something similar to my answer to another question.

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

Which you can use as :

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

Extending ProductArgs transforms or test(aa _, "foo") (which is actually test.apply(aa _, "foo")) to test.applyProduct((aa _) :: "foo" :: HNil). In applyProduct we check that the HList consists of a function and valid arguments.


We shouldn't need the NarrowArgs <:< Args, but ProductArgs seems to give the same result as SingletonProductArgs.

Upvotes: 3

justAbit
justAbit

Reputation: 4256

It's because AA does not accept variable number of arguments, change it to:

def AA(args: String*) :Boolean

Upvotes: 0

Related Questions