alifirat
alifirat

Reputation: 2937

Function returning a generic array

I have one issue for a function that I wrote about the conversion of one Array[Byte] to a Array[T]. The function in question :

def getPoints[T](bytes : Array[Byte]) : Array[T] = {
      val byteBuffer = ByteBuffer.wrap(bytes)
      byteBuffer.order(ByteOrder.LITTLE_ENDIAN)
      val data = Array.ofDim[T](bytes.length / biosRecord.byteEncoding)
      if(biosRecord.byteEncoding == 2) {
        byteBuffer.asShortBuffer.get(data)
        data
      } else if(biosRecord.byteEncoding == 4) {
        byteBuffer.asIntBuffer().get(data)
        data
      } else null
    }

biosRecord is a case class with a int field (byteEncoding).

I know there is two problems in this code :

  1. To return a generic array, I need to use Manifest.
  2. In the first if branch, the inferred type is Array[Short] and in the second one is Array[Int]. This is why I tried to use a generic type T but it not works.

What I get at the compilation time :

[error]   (x$1: Array[Short])java.nio.ShortBuffer <and>
[error]   (x$1: Int)Short
[error]  cannot be applied to (Array[T])
[error]         byteBuffer.asShortBuffer.get(data)

[error]   (x$1: Array[Int])java.nio.IntBuffer <and>
[error]   (x$1: Int)Int
[error]  cannot be applied to (Array[T])
[error]         byteBuffer.asIntBuffer().get(data)

What do I need to do in order to make this generic function compiles ?

Upvotes: 1

Views: 7980

Answers (1)

Tzach Zohar
Tzach Zohar

Reputation: 37832

The signature def getPoints[T](bytes : Array[Byte]) : Array[T] means that the caller can decide what T is. For instance, by calling:

val myResult = getPoints[String](myBytes)

I'm making getPoints return an Array[String], regardless of the value of myBytes.

In other words - what you're trying to do is not possible. You cannot parameterize a method's type based on "decisions" inside the method body.

Perhaps what you want to do here is use the best common type that is a superclass of all possible return types. In this case:

def getPoints(bytes : Array[Byte]) : Array[AnyVal] = {
    // can return Array[Int], Array[Short]...
}

This way, the caller can't force the type, and doesn't know the type, all they know is that it's one of the subclasses of AnyVal.

Upvotes: 4

Related Questions