Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: Constructor taking either Seq or varargs

Tags:

I am guessing that, for compatibility reasons, the type of vararg parameters Any* is Array[Any] - please correct this if I'm wrong. However, this does not explain the following error:

class Api(api_url: String, params: Seq[(String, String)]) {   def this(api_url: String, params: (String, String)*)     = this(api_url, params.seq) } 

This code does not compile, but gives the warning:

double definition: constructor Api:(api_url: String, params: (String, String)*)Api and constructor Api:(api_url: String, params: Seq[(String, String)])Api at line 13 have same type after erasure: (api_url: java.lang.String, params: Seq)Api

So how do I define a constructor taking either varargs or a sequence?

like image 746
wen Avatar asked Aug 12 '11 12:08

wen


2 Answers

A method taking varargs is also always taking a sequence, so there is no need to define an auxiliary constructor or overloaded method.

Given

class Api(api_url: String, params: (String, String)*) 

you can call it like this

new Api("url", ("a", "b"), ("c", "d")) 

or

val seq = Seq(("a", "b"), ("c", "d")) new Api("url", seq:_*) 

Also, in your question, you are calling method seq on the params parameter. This probably does not do what you intended. seq is used to ensure that operations on the resulting collection are executed sequentially instead of in parallel. The method was introduced with the parallel collections in version 2.9.0 of Scala.

What you probably wanted to use was toSeq, which returns the collection it is used on converted to a Seq (or itself if it is already a Seq). But as varargs parameters are already typed as Seq, that is a no-op anyway.

like image 127
Ruediger Keller Avatar answered Oct 01 '22 13:10

Ruediger Keller


No: actually, Any* is actually almost identical to Seq[Any], not to Array[Any].

To disambiguate between the two, you can use the technique to add a dummy implicit parameter to make the signature different:

class Api(api_url: String, params: Seq[(String, String)]) {   def this(api_url: String, params: (String, String)*)(implicit d: DummyImplicit) =     this(api_url, params) } 
like image 31
Jean-Philippe Pellet Avatar answered Oct 01 '22 11:10

Jean-Philippe Pellet