标签: scala-reflect

Scala解析器削减最后一个括号

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 scala-compiler scala-2.11 scala-reflect scala-2.12

5
推荐指数
1
解决办法
229
查看次数

为什么我们必须显式指定ClassTag类型类

现在scala已经使用类型类迭代了JVM 类型的擦除修复ClassTag,为什么它是一个选择加入,而不是让编译器总是捕获运行时检查的类型签名.使它具有隐式参数化类型约束将使得classTag[T]无论泛型参数声明如何都可以调用.

编辑:我应该澄清,我并不是说scala应该改变幕后的签名,总是包含在内ClassTag.相反,我的意思是,因为ClassTag显示scala可以捕获运行时类型信息并因此避免类型擦除限制,为什么不能将该捕获隐含为编译器的一部分,以便该信息始终在scala代码中可用?

我怀疑它是向后兼容性,java生态系统兼容性,二进制大小或运行时开销相关,但这些只是猜测.

scala typeclass scala-reflect

5
推荐指数
1
解决办法
796
查看次数

通过对String的反射来定义spark udf

我试图从包含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)

scala apache-spark scala-reflect udf spark-dataframe

4
推荐指数
1
解决办法
1466
查看次数

如何在 Scala 宏中获取更高级类型参数的树

我正在尝试编写一个宏来简化一些与 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 和我自己的项目之间的区别是。

scala higher-kinded-types scala-macros scala-reflect

4
推荐指数
1
解决办法
231
查看次数

从Seq [T]中提取类型T

我有一个案例类,其中有两个字段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]) …

scala scala-reflect

3
推荐指数
1
解决办法
59
查看次数

符号是案例对象吗?

{ 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,但是如果将密封的特性定义为依赖类型,则无效.

scala scala-reflect

2
推荐指数
1
解决办法
524
查看次数

如何以编程方式编译和运行 Scala 代码

我有以下代码,我想即时编译并运行它。

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)

reflection scala scala-compiler scala-reflect

2
推荐指数
1
解决办法
302
查看次数

通过反射实例化 Scala 类/案例类

描述

我正在尝试构建一个能够将 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

2
推荐指数
1
解决办法
544
查看次数

如何将方法的返回类型与 Scala 本机或 TypeTag 进行比较?

所以,我正在使用 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)

reflection scala scala-reflect

2
推荐指数
2
解决办法
140
查看次数

在 Scala 中,是否可以实例化泛型类型 T 的对象?

在 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)

generics reflection types scala scala-reflect

2
推荐指数
1
解决办法
338
查看次数