How can I pass a type as a parameter in scala?

10,002

Solution 1

You can't store types in variables. And also you can't simply cast a byte stream to a type. What you can do is to use a serialization library like protobuf. What exactly is your use-case though? Where do you get the data from? Is it also a java/scala app? It would maybe be easier to help you, if you would tell, what exactly you want to do.

Solution 2

You can get types as values with Scala 2.10 (when it comes out). Before that, the best you can get is the class (classOf[String], for example), but that loses any type parameter.

Even with Scala 2.10 there are some serious limitations you'll come up against. See a recent blog post of mine for an example.

Share:
10,002
rsan
Author by

rsan

Updated on June 11, 2022

Comments

  • rsan
    rsan almost 2 years

    I'm having a really hard time trying to figure out how to store or pass a type in scala.

    What I want to achive is something like this:

    abstract class Foo( val theType : type )
    object Foo{
       case object Foo1 extends Foo(String)
       case object Foo2 extends Foo(Long)     
    }
    

    So at some point I can do this:

    theFoo match{
       case String => "Is a string"
       case Long => "Is a long"
    }
    

    and when obtaining the object being able to cast it:

    theFoo.asInstanceOf[Foo1.theType]
    

    Is this possible? If is possible, is a good aproach? What I'm trying to achieve ultimately is writing a pseudo schema for byte stream treatment. E.g if I have an schema Array(Foo1,Foo1,Foo2,Foo3,Foo1) I could parse Arrays of bytes that complain with that schema, if at some point I have a different stream of bytes I could just write a new schema Array(Foo3, Foo4, Foo5) without having to reimplement parsing logic.

    Regards,


    EDIT as requested

    Suppose I have an Array[Byte] = A973928CB3883FB123 named Command1

    The data in this bytes is fixed in position and length. In other words, I know that position 1-4 is for example a small date, the 5-9 is the name of a customer, etc etc.

    What I want is to write a single parsing function that takes as only parammeter a schema and returns the actual values of every param in the schema.

    trait Command{
    
      //This is implemented in every command
      val schema : List[Tuple[String,Int,Int,Type]]  //Position,Size,DataType
    
      def parse() : List[Tuple[String,Int,Int,Type,Any]] = schema.map(//match using the type)
    }
    
    class Command1 extends Command {
      override val schema = List[Tuple("theName",0,10,String),Tuple("myType",10,12,MyType),Tuple("theId",13,20,Long)]
      val theActualName = parse().find(_._1 == "theName")._5.asInstanceOf[String] //I would like to avoid this cast
    
    }
    

    I hope this clarify what I'm trying to do.

  • Rex Kerr
    Rex Kerr over 11 years
    What about java.lang.Class and scala.reflect.Manifest (not to mention TypeTag in the upcoming 2.10)?
  • drexin
    drexin over 11 years
    Okay, right, but that is not storing a type and anyway it seems that it wouldn't lead to a solution here (that's why I didnd't mention it), because even when the OP had the type simply casting the bytes wouldn't work (but you know that ;-) ).
  • rsan
    rsan over 11 years
    Thanx in advance for the support. I would't like to add so much overkill including a specialized serialization library, I would like to keep it simple to the end. I will edit the post to add more information of what I want to achive more concretly.
  • Rex Kerr
    Rex Kerr over 11 years
    It is as close to storing a type as you can get given that it's runtime information and types must check at compile-time.
  • drexin
    drexin over 11 years
    I know @RexKerr, but I don't think, that it helps here.
  • rsan
    rsan over 11 years
    Thanks Danie, I accepted @drexin answer because we was first but your blog entry was really helpful. Thanks again.