0

Is it possible pass generic parameter using class:

  def m(clazz: Class[_]): Unit = {
    m2[] //here I want to exact type (that I should have because I have Class)
  }

  def m2[C: ClassTag]() : List[C] = {
    println("hi")
    List.empty
  }

Any Ideas?

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
SLA VA
  • 53
  • 3
  • 2
    What is the meta problem you are trying to solve? – Luis Miguel Mejía Suárez Aug 12 '21 at 12:23
  • I needed it for macros which requires ClassTag of T. But I want to do it in runtime (so I think it will not work). More general use case: we have class `clazz` and generic method that defined like `m2` . Is it possible in runtime make something like `m2[clazz]()` – SLA VA Aug 12 '21 at 14:45
  • In other words: is it exists bridge between compile time generic param defined by programmer and runtime class? 1. `List[MyClass]` 2.`val clazz = classOf[MyClass]; List[clazz]` . In this example it's meaningless. Something that stores runtime info should be used (like arrays) – SLA VA Aug 12 '21 at 14:58

2 Answers2

0

IIUC you want to call a method that requires a ClassTag while all you have is a Class. You can create a ClassTag from a Class like this:

def m(clazz: Class[_]): Unit = {
  m2()(ClassTag(clazz))
}
Jasper-M
  • 14,966
  • 2
  • 26
  • 37
  • class is type parameter (not argument) – SLA VA Aug 12 '21 at 14:49
  • 3
    You cannot turn a value (`clazz: Class[_]`) into a type parameter. The first lives at runtime and the other at compile time. In your example you don't need the type parameter either. What you need is the `ClassTag`. Otherwise you'll have to show an example where the actual type parameter is required. – Jasper-M Aug 12 '21 at 14:56
  • In my original use case it was library macros that defined like `m2`. So imagine so library that has public api that takes `[T: ClassTag]` as param but has no public api that takes `Class[_]` as param. It has some sense? – SLA VA Aug 13 '21 at 11:51
0

ClassTags (as well as TypeTags and WeakTypeTags) are for persisting some compile-time information till runtime. You want to do something in reverse direction. You want, having runtime information (clazz: Class[_]), to do something at compile time (specify type parameter C of m2). So ClassTags are irrelevant.

You can call compiler at runtime

import scala.tools.reflect.ToolBox
import scala.reflect.runtime.currentMirror

object App {
  val tb = currentMirror.mkToolBox()

  def m(clazz: Class[_]): Unit = {
    tb.eval(tb.parse(s"import App._; m2[${clazz.getName}]"))
  }

  def m2[C]() : List[C] = {
    println("hi")
    List.empty
  }

  def main(args: Array[String]): Unit = {
    m(classOf[String]) //hi
  }
}
libraryDependencies ++= Seq(
  scalaOrganization.value % "scala-reflect" % scalaVersion.value,
  scalaOrganization.value % "scala-compiler" % scalaVersion.value,
)
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66