Can we get the type of val s: String
using reflection from the outside of the function f
?
val f = (r: {val s: String}) => {
}
Can we get the type of val s: String
using reflection from the outside of the function f
?
val f = (r: {val s: String}) => {
}
scala> import scala.reflect.runtime.{universe => ru}
import scala.reflect.runtime.{universe=>ru}
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> def typeOf[T: ru.TypeTag](x: T) = ru.typeOf[T] // capture compile-time type info
typeOf: [T](x: T)(implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.Type
scala> val f = (r: {val s: String}) => {}
f: AnyRef{val s: String} => Unit = <function1>
scala> val tpe = typeOf(f)
tpe: reflect.runtime.universe.Type = scala.AnyRef{val s: String} => Unit
scala> ru.showRaw(tpe)
res0: String = TypeRef(ThisType(scala), scala.Function1, List(RefinedType(List(TypeRef(ThisType(scala), newTypeName("AnyRef"), List())), Scope(newTermName("s"))), TypeRef(ThisType(scala), scala.Unit, List())))
scala> val ru.TypeRef(_, _, refinement :: _) = tpe
refinement: reflect.runtime.universe.Type = scala.AnyRef{val s: String}
With Scala reflection one can also generate mocks for structural types as follows: https://gist.github.com/4008389. The linked gist does this using toolboxes and runtime reflection, but this scenario looks implementable with macros as well.
warning: abstract type pattern reflect.runtime.universe.TypeRef is unchecked since it is eliminated by erasure
–
Gompers TypeRef
is an abstract type (scala.reflect.api.Types#TypeRef) and abstract types are erased during compilation, losing their identity. Therefore when the pattern matcher tries to emit something.isInstanceOf[TypeRef]
, this causes an unchecked warning. However when there's an implicit classtag in scope, the pattern matcher can make use of it to emit something like classtag.runtimeClass.isAssignableFrom(something.getClass)
(where classtag points to the underlying scala.reflect.internal.Types#TypeRef, which is a full-fledged class, not an abstract type). –
Lorenzetti © 2022 - 2024 — McMap. All rights reserved.
r
. – Templateimport reflect.runtime._, universe._; currentMirror.reflectClass(currentMirror.reflect(f).symbol).symbol.typeSignature.member(newTermName("apply")).asTerm.alternatives.map(_.typeSignature)
– IckycurrentMirror.reflect(f)
reflects upon a runtime value, therefore it only has access to runtime type information, erased during compilation. – Lorenzetti