Reputation: 18024
I have a method foo
that takes Seq[Any]
. For example:
def foo(a:Seq[Any]) = println(a.size)
foo(Seq("hi", 1, true)) // prints 3
I would have liked to avoid writing Seq
every time. So I would like to define a method bar
that I could call as:
bar("hi", 1, true)
having the same effect as calling foo(Seq("hi", 1, true))
.
Defining the following:
def bar(b:Any *) = foo(b)
and using it as:
bar("hi", 1, true) // prints 1
does not work as expected. It assigns b
to the first element of the Seq
passed to foo
. Is there any way I can define bar
so that it correctly invokes foo
?
Upvotes: 0
Views: 414
Reputation: 13985
You should not be having that problem, That code should work fine and is working fine for me.
scala> def foo(a:Seq[Any]) = println(a.size)
foo: (a: Seq[Any])Unit
scala> def bar( b: Any* ) = foo( b )
bar: (b: Any*)Unit
scala> bar( "hi" , 34, 23 )
3
scala> bar( "hi" , 34, true )
3
The reason this is happening is becasue *-paramters
are implicitly received as Seq
in function-body. Which means even if you pass multiple varargs
paramters, these will be received as a Sequence inside your function.
You can again convert a Sequence of things to multiple varargs paramters using the _*
annotation.
_*
is the special annotation
that is usable only in arguments
to *-parameter
of a function. It makes any sequence
to be passed as a *-parameter
.
Following examples will clear things.
scala> val l = List( 4, 5, 6, 7, 3, 6, 3 )
l: List[Int] = List(4, 5, 6, 7, 3, 6, 3)
scala> def pp( ints: Int* ) = println( ints )
pp: (ints: Int*)Unit
// All Int* are implicitly received as a Seq[ Int ]
// Hence, ints will be a Seq[ Int ] in function body
// ( WrappedArray[ int ] in this case ) in function body.
scala> pp( 4, 5, 6 )
WrappedArray( 4, 5, 6 )
// Received as List[ Int ] in this case
scala> pp( l: _* )
List(4, 5, 6, 7, 3, 6, 3)
scala> def a( ints: Int* ) = ints.sum
a: (ints: Int*)Int
// passing a list wont work
scala> a( l )
<console>:11: error: type mismatch;
found : List[Int]
required: Int
a( l )
^
// list passed as multiple parameters
scala> a( l: _* )
res8: Int = 34
Upvotes: 1
Reputation: 18024
Found the answer. Defining bar
as
def bar(b:Any *) = foo(b.toSeq)
does the trick.
Upvotes: 0