Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_121).
Type in expressions for evaluation. Or try :help.
scala> :paste
// Entering paste mode (ctrl-D to finish)
import scala.reflect.runtime._
import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox
val mirror = universe.runtimeMirror(universe.getClass.getClassLoader)
val toolbox = mirror.mkToolBox(options = "-Yrangepos")
val text =
"""
|libraryDependencies ++= Seq("org.scala-lang" % "scala-compiler" % "2.10.4") map {
| (dependency) =>{
| dependency
| }
|}
""".stripMargin
val parsed = toolbox.parse(text)
val parsedTrees = parsed match {
case Block(stmt, expr) => …Run Code Online (Sandbox Code Playgroud) 现在scala已经使用类型类迭代了JVM 类型的擦除修复ClassTag,为什么它是一个选择加入,而不是让编译器总是捕获运行时检查的类型签名.使它具有隐式参数化类型约束将使得classTag[T]无论泛型参数声明如何都可以调用.
编辑:我应该澄清,我并不是说scala应该改变幕后的签名,总是包含在内ClassTag.相反,我的意思是,因为ClassTag显示scala可以捕获运行时类型信息并因此避免类型擦除限制,为什么不能将该捕获隐含为编译器的一部分,以便该信息始终在scala代码中可用?
我怀疑它是向后兼容性,java生态系统兼容性,二进制大小或运行时开销相关,但这些只是猜测.
我试图从包含scala函数定义的字符串中定义spark(2.0)中的udf.这是片段:
val universe: scala.reflect.runtime.universe.type = scala.reflect.runtime.universe
import universe._
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox
val toolbox = currentMirror.mkToolBox()
val f = udf(toolbox.eval(toolbox.parse("(s:String) => 5")).asInstanceOf[String => Int])
sc.parallelize(Seq("1","5")).toDF.select(f(col("value"))).show
Run Code Online (Sandbox Code Playgroud)
这给了我一个错误:
Caused by: java.lang.ClassCastException: cannot assign instance of scala.collection.immutable.List$SerializationProxy to field org.apache.spark.rdd.RDD.org$apache$spark$rdd$RDD$$dependencies_ of type scala.collection.Seq in instance of org.apache.spark.rdd.MapPartitionsRDD
at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2133)
at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1305)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2024)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1942)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1808)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2018)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1942)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1808)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at org.apache.spark.serializer.JavaDeserializationStream.readObject(JavaSerializer.scala:75)
at org.apache.spark.serializer.JavaSerializerInstance.deserialize(JavaSerializer.scala:114)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
at org.apache.spark.scheduler.Task.run(Task.scala:85)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:274)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个宏来简化一些与 monad 相关的代码(我使用cats 1.6.0 作为Monads)。现在我只想能够编写lift[F](a)whereF是一个一元类型的构造函数,并将其扩展为a.pure[F]. 看起来很简单,但我无法让它工作。
现在我有这个代码来帮助类型推断:
object Macros {
class LiftPartiallyApplied[F[_]] {
def apply[A](a: A): F[A] = macro MacroImpl.liftImpl[F, A]
}
def lift[F[_]] = new LiftPartiallyApplied[F]
}
Run Code Online (Sandbox Code Playgroud)
对于宏的实际实现:
object MacroImpl {
def liftImpl[F[_], A](c: blackbox.Context)(a: c.Tree)(implicit tt: c.WeakTypeTag[F[_]]): c.Tree = {
import c.universe._
q"$a.pure[${tt.tpe.typeConstructor}]"
}
}
Run Code Online (Sandbox Code Playgroud)
现在我可以像这样调用宏lift[List](42),它会扩展为42.pure[List],太好了。但是当我用更复杂的类型调用它时,比如lift[({type F[A] = Either[String, A]})#F](42),它会扩展到42.pure[Either],这显然是坏的,因为它Either是一个二进制类型的构造函数而不是一元类型的构造函数。问题是我只是不知道该放什么而不是${tt.tpe.typeConstructor}……
// 编辑:由于人们显然无法重现该问题,因此我制作了一个完整的存储库:https : //github.com/mberndt123/macro-experiment 我现在将尝试找出 Dmytro 和我自己的项目之间的区别是。
我有一个案例类,其中有两个字段Seq[Objects]。这两个对象属于两个不同的案例类。
case class Passport(country: String, name: String)
case class DrivingLicence(code: String, name: String)
case class Docs(passports : Seq[Passport], driv: Seq[DrivingLicence])
val pass1 = Passport("UK", "Michael")
val pass2 = Passport("USA", "Michael")
val driv1 = DrivingLicence("A2", "Mich")
val driv2 = DrivingLicence("A4", "Mich")
val docs = Docs(Seq(pass1,pass2), Seq(driv1,driv2))
Run Code Online (Sandbox Code Playgroud)
我可以生成具有所有属性及其类型的地图,如下所示:
val r = currentMirror.reflect(docs)
val mapType = r.symbol.typeSignature.members.toStream
.collect{case s : TermSymbol if !s.isMethod => r.reflectField(s)}
.map(r => r.symbol.name.toString.trim -> r.symbol.typeSignature)
.toMap
println("Map of Types: "+mapType)
Run Code Online (Sandbox Code Playgroud)
输出为:
地图类型:地图(driv-> Seq [DrivingLicence],护照-> Seq [Passport]) …
{ sealed trait Sealed; case object Foo extends Sealed; case class Bar(s: String) extends Sealed; trait Baz extends Sealed }
import scala.reflect.runtime.universe._
val List(bar, baz, foo) = symbolOf[Sealed].asClass.knownDirectSubclasses.toList
Run Code Online (Sandbox Code Playgroud)
我已经尝试过了.asClass.primaryConstructor.isStatic,但是如果将密封的特性定义为依赖类型,则无效.
我有以下代码,我想即时编译并运行它。
object HelloWorld {
def main(args: Array[String]): Unit = {
println("Hello, world!")
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,我已经尝试过如下所示:
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox
object MainScala {
def main(args: Array[String]): Unit = {
val toolbox = currentMirror.mkToolBox()
val source =
"""
|object HelloWorld {
| def main(args: Array[String]): Unit = {
| println("Hello, world!")
| }
|}
|""".stripMargin
val tree = toolbox.parse(source)
val binary = toolbox.compile(tree)
var c = binary.getClass
val m = c.getMethod("main", classOf[Array[String]])
val params = Array("Apple", "Banana", "Orange")
m.invoke(null, null)
}
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试构建一个能够将 aMap[String, Any]转换为class/case class实例的工具。如果类定义包含未在 中指定的默认参数,Map则将应用默认值。
以下代码片段允许检索主类构造函数:
import scala.reflect.runtime.universe._
def constructorOf[A: TypeTag]: MethodMirror = {
val constructor = typeOf[A]
.decl(termNames.CONSTRUCTOR)
// Getting all the constructors
.alternatives
.map(_.asMethod)
// Picking the primary constructor
.find(_.isPrimaryConstructor)
// A class must always have a primary constructor, so this is safe
.get
typeTag[A].mirror
.reflectClass(typeOf[A].typeSymbol.asClass)
.reflectConstructor(constructor)
}
Run Code Online (Sandbox Code Playgroud)
鉴于以下简单的类定义:
class Foo(a: String = "foo") {
override def toString: String = s"Foo($a)"
}
Run Code Online (Sandbox Code Playgroud)
Foo提供两个参数时,我可以轻松创建一个新实例:
val bar = constructorOf[Foo].apply("bar").asInstanceOf[Foo]
bar: …Run Code Online (Sandbox Code Playgroud) reflection scala default-value default-parameters scala-reflect
所以,我正在使用 Scala 反射库,并且我正在尝试检查一个方法是否符合给定的类型。为简化起见,我试图仅检查其输出。
我现在拥有的是:
val returnType = methodSymbol.returnType
// returnType: reflect.runtime.universe.Type = java.lang.String
Run Code Online (Sandbox Code Playgroud)
所以,我可以读到它是一个字符串,但它有这种可怕的类型reflect.runtime.universe.Type。我到底如何比较检查这个返回类型是否是一个简单的字符串?我什至尝试使用足够简单的 TypeTags,但是将 a 转换Type为 aTypeTag是一项巨大的努力,我不相信这样简单的任务无法通过更简单的方式完成。
那么,我如何将它与 String 进行比较并简单地返回一个布尔值?我想简单地调用 atoString()并尝试将其解析回正常类型,但这对代码来说真的很恶心,IMO。此外,我不能简单地指定方法名称,因为我正在处理方法列表,稍后会提供更多方法。
我已经看到了一些问题,甚至这个(在我看来,荒谬复杂的)回答有关如何将类型转换为TypeTag,但同样,我被复杂的这样一个简单的任务级别百思不得其解。我已经在考虑拔掉我稀少的头发了。帮助表示赞赏。
编辑:我已经设法对字符串本身进行比较,但没有对返回字符串的方法进行比较。
为了比较 String 返回类型,我正在做:
val returnType = methodSymbol.returnType
returnType =:= typeTag[String].tpe
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试使用继承和方法检查它时,使用<:<,它不起作用。澄清一下,B 扩展了 Trait A,类型签名是() => B,但我在编码时无法匹配
val typeSig = methodSymbol.typeSig
typeSig <:< typeTag[() => A].tpe
Run Code Online (Sandbox Code Playgroud) 在 Scala 中,即使解决方案不优雅,是否可以实例化/创建泛型类型 T 的新对象?是否可以使用反射来实现这一点?
例如,我对以下内容感兴趣:
case class Person(name: String, age: Int)
Run Code Online (Sandbox Code Playgroud)
假设我想执行以下操作来创建一个 Person 类型的对象:
def createObject[T](fieldValues: Seq[Any]): T = {
... T(fieldValues)
}
val person = createObject[Person](Seq("Bob", 20))
Run Code Online (Sandbox Code Playgroud) scala ×10
scala-reflect ×10
reflection ×4
apache-spark ×1
generics ×1
scala-2.11 ×1
scala-2.12 ×1
scala-macros ×1
typeclass ×1
types ×1
udf ×1