0

I have a variable of a trait that accepts multiple datatypes {Int, Long, String, Double}.

I need to do some math operation on this variable. So I try to convert the variable to an ArrayBuffer [Any].

def toArray (x: MultiV): ArrayBuffer [Any] = {
    val a = new ArrayBuffer[Any]()
    for (i <- 0 until rows) a += x(i)   // x(i) belongs to set {Int, Long, String, Double}
    a
}

Now as I need to perform some operations on this try to convert ArrayBuffer to their individual types.

def printInd (a: ArrayBuffer [Any], b: Seq[Int]) = {
    val v = a(0) match {
        case _: Double   => a.asInstanceOf [ArrayBuffer [Double]]
        case _: Int      => a.asInstanceOf [ArrayBuffer [Int]]
        case _: Long     => a.asInstanceOf [ArrayBuffer [Long]]
        case _: String   => a.asInstanceOf [ArrayBuffer [String]]
        case _  =>  println ("printInd: type not supported")
    }
    for (i <- b) print(v(i) + " ")  // Error: Any does not take parameters
}

I get an error on the print statement saying

Any does not take parameters    
print(v(i))  
      ^

v is of class ArrayBuffer so I am assuming it should take an integer parameter to return the element at that index. (Also I assume, if a(0) is Int, v is ArrayBuffer [Int]. Or is it still ArrayBuffer [Any]?).
Can anyone please explain what I am understanding wrong.

3
  • 1
    I updated the code. I was thinking the match statement will assign a.asInstanceOf[...] to val v. Commented Jun 20, 2018 at 17:10
  • 1
    If you discard type information, you are likely to spend a lot of your time arguing with the Scala type checker. Perhaps MultiV should be a generic type. It looks like the values you extract into the buffer will all be of the same type (all Double or all Int etc.). Can you make that an explicit type parameter? Commented Jun 20, 2018 at 18:07
  • Compare the title and the error message in the question. Commented Jun 20, 2018 at 20:03

2 Answers 2

3

The println statement returns a Unit. Thus, the type of v is inferred to be as a lower bound of ArrayBuffer[Int] and Unit, which is Any.

You can fix this as follows:

def printInd (a: ArrayBuffer [Any], b: Seq[Int]) = {
    val v = a(0) match {
        case _: Double   => a.asInstanceOf [ArrayBuffer [Double]]
        case _: Int      => a.asInstanceOf [ArrayBuffer [Int]]
        case _: Long     => a.asInstanceOf [ArrayBuffer [Long]]
        case _: String   => a.asInstanceOf [ArrayBuffer [String]]
        case _  =>  a
    }
    for (i <- b) print(v(i) + " ")
}

or like this:

def printInd (a: ArrayBuffer [Any], b: Seq[Int]) = {
    val v = a(0) match {
        case _: Double   => a.asInstanceOf [ArrayBuffer [Double]]
        case _: Int      => a.asInstanceOf [ArrayBuffer [Int]]
        case _: Long     => a.asInstanceOf [ArrayBuffer [Long]]
        case _: String   => a.asInstanceOf [ArrayBuffer [String]]
        case _  =>  throw new IllegalArgumentException("Unexpected type")
    }
    for (i <- b) print(v(i) + " ")
}

but in both cases, it doesn't buy you anything, because the most specific type that you can assign to v is still something like ArrayBuffer[_]. You have to do something with additional type information inside of the match, otherwise it's useless.

Sign up to request clarification or add additional context in comments.

Comments

0

v is of type Any according to the error message.

You need to make your case _ => ... return an ArrayBuffer as well.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.