IttayD
IttayD

Reputation: 29123

capture types of varargs parameters

I'd like to define a method accepting varargs, so that I get the types with which it was called even in the case of nulls.

def foo(args: Any*) = ....

val s: String = null

foo(1, s) // i'd like to be able to tell in foo that args(0) is Int, args(1) is String

Upvotes: 3

Views: 355

Answers (3)

Kristian Domagala
Kristian Domagala

Reputation: 3696

In terms of the original question, I'm pretty sure it's not possible.

Without knowing exactly what you're trying to achieve (ie, why it must be a variable-length list of arbitrary types), it is difficult to offer an alternative. However, there are two things that came to my mind when I read the question that may be an option for you: Default argument values in combination with named arguments (requires Scala 2.8+), and the HList data type (less likely).

Upvotes: 4

michael.kebe
michael.kebe

Reputation: 11085

Because you are using Any as type you cannot get the type of the arguments. Type Any doesn't have the getClass method (it even isn't a reference class at all). See http://www.scala-lang.org/node/128 for more information.

What you can try is this:

def foo(args: Any*) = args.map { arg => {
  arg match {
    case reference:AnyRef => reference.getClass.toString
    case null => "null"
}}}

val s: String = null

val result = foo("a", 1, 'c', 3.14, s, new Object, List(1), null)

result.foreach(println)

This outputs:

class java.lang.String
class java.lang.Integer
class java.lang.Character
class java.lang.Double
null
class java.lang.Object
class scala.collection.immutable.$colon$colon
null

Upvotes: 3

Michel Krämer
Michel Krämer

Reputation: 14647

If you're using Any as parameter type you will not be able to determine the type of the arguments statically. You will have to use instanceof or pattern matching:

def foo(args: Any*) = for (a <- args) a match {
  case i: Int =>
  case s: String =>
  case _ =>
}

Unfortuntely, this is not able to handle null values.

If you want static types you will have to use overloading:

def foo[A](arg1: A)
def foo[A, B](arg1: A, arg2: B)
def foo[A, B, C](arg1: A, arg2: B, arg3: C)
...

Upvotes: 6

Related Questions