2

I'd like to experiment with the use of a dynamic data model with a reflective library that uses typeOf[].

I've defined a class at runtime with a Scala reflection ToolBox in 2.11:

import scala.tools.reflect.ToolBox
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{ currentMirror => cm }

def cdef() = q"case class C(v: String)"
val tb = cm.mkToolBox()
val csym = tb.define(cdef())
def newc(csym: Symbol) = q"""new ${csym}("hi")"""
val obj = tb.eval(newc(csym))

I'm able to circumvent the typeOf[] call by entering Scala reflection via the ClassSymbol instead, but that requires modifying a library over which I have no immediate control.

Is there any way that I can use it as a type parameter in a library whose entry point is typeOf[]?

I've tried:

The only way I found to go from a value to something that I could use in the type position was use Java reflection to invoke the companion class' apply method and call .type on the result:

val method_apply = obj.getClass.getMethod("apply", "".getClass)
val typeTemplate = method_apply.invoke(obj, "hello")
type MyType = typeTemplate.type

(Keeping with the naming scheme of @xeno_by and @travisbrown 's menagerie of odd types, I might call this "Frankenstein's Type", because it is made from parts, given life at the wrong time, not quite a substitute for the original, and given that this is all happening at runtime, should probably be burned with fire.)

This type alias works as a type parameter is some cases. But in the case of typeOf[MyType], the the compiler makes a TypeTag before the runtime type is defined, so typeOf[MyType] returns a type member that doesn't correspond to the runtime type/class (e.g. TypeTag[package.Example.MyType] instead of TypeTag[package.C])

Should I expect the ToolBox to have generated a TypeTag, and if so, how do I use it?

If I have to make a TypeTag at runtime, this question shows me how, but then how do I attach it to whatever I use as a type parameter?

Thanks for any ideas,

-Julian

Community
  • 1
  • 1
Julian Peeters
  • 853
  • 1
  • 6
  • 19
  • Could you give an example of what you want to achieve? What method are you calling that requires you to provide a typeOf? – Eugene Burmako Sep 02 '14 at 07:13
  • Similar to this [example](https://github.com/julianpeeters/toolbox-salat-example/blob/master/src/main/scala/Main.scala#L60) using Salat, but with [Scalavro](https://github.com/GenslerAppsPod/scalavro) instead. It looks like `AvroType[T]` uses an implicit TypeTag to get runtime class info for T, so I assumed (perhaps naively) that if I could do `typeOf[MyType]` – Julian Peeters Sep 04 '14 at 07:06
  • ...that I could also do `AvroType[MyType]`. [This branch](https://github.com/julianpeeters/toolbox-salat-example/blob/scalavro/src/main/scala/Main.scala) shows the error (that there is no class corresponding to the de-aliased type parameter). – Julian Peeters Sep 04 '14 at 07:12
  • If it's helpful, [here's](https://github.com/julianpeeters/toolbox-scalavro/commit/a094109d50eabfbaf366261ffa9a9b1675270c42#diff-9d3013c5d648f8bf6caa21997834fa9dR35) a crude fork of Scalavro that shows a workaround by passing in the toolbox and the class symbol. – Julian Peeters Sep 05 '14 at 02:40
  • 1
    Yeah, I think something along these lines will work. You'll need to create a dummy type and then create a fake type tag for that type that contains the scala.reflect.runtime.Type that you would like to pass in. A type alias isn't dummy enough imo, so I'd go for something like `class Foo { type T; implicit val tag: TypeTag[T] = createTypeTag(yourTpe).asInstanceOf[TypeTag[T]] }; val dummy = new Foo; import dummy._`. – Eugene Burmako Sep 13 '14 at 12:04
  • Why did you pass in a toolbox btw? – Eugene Burmako Sep 13 '14 at 12:04
  • That's fantastic. I passed in the toolbox to give Scalavro access to the toolbox's special classloader, so it could use a classloader mirror to reflect on the companion's apply method when mapping default values. – Julian Peeters Sep 21 '14 at 07:45

0 Answers0