标签: scala-macros

如何在 Scala 中使用没有参数的构造函数参数创建 Case Class 的实例?

我正在制作一个通过反射字段值设置的 Scala 应用程序。这工作正常。

但是,为了设置字段值,我需要一个创建的实例。如果我有一个带有空构造函数的类,我可以使用 classOf[Person].getConstructors 轻松做到这一点....

但是,当我尝试使用具有非空构造函数的 Case 类执行此操作时,它不起作用。我拥有所有字段名称及其值,以及我需要创建的对象类型。我可以用我所拥有的以某种方式实例化 Case Class 吗?

我唯一没有的是来自 Case Class 构造函数的参数名称,或者一种在没有参数的情况下创建它然后通过反射设置值的方法。

我们来看例子。

我有以下

case class Person(name : String, age : Int)
class Dog(name : String) {
    def this() = {
        name = "Tony"
    }
}

class Reflector[O](obj : O) {

    def setValue[F](propName : String, value : F) = ...

    def getValue(propName : String) = ...
}

//This works
val dog = classOf[Dog].newInstance()
new Reflector(dog).setValue("name", "Doggy")

//This doesn't
val person = classOf[Person].newInstance //Doesn't work

val ctor …
Run Code Online (Sandbox Code Playgroud)

reflection macros scala case-class scala-macros

7
推荐指数
1
解决办法
1万
查看次数

Scala 3 中的宏注释

以下是三年多前的Macros: The Plan for Scala 3中的一段话:

例如,我们可以定义一个宏注释 @json,将 JSON 序列化器添加到一种类型中。

知道这在 Scala 3 中如何/是否可行吗?

更一般地说,Scala 3 中有什么可以提供“宏注释”功能吗?以下是宏注释 - Scala 2.13的引用:

与以前版本的宏天堂不同,2.0 中的宏注释在以下意义上是正确的:1) 不仅适用于类和对象,而且适用于任意定义,2)允许扩展类来修改甚至创建伴生对象

scala scala-macros scala-macro-paradise scala-3

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

Scala宏指定解构函数的参数

我目前正在玩一些宏,但也许这是一个坏主意,但这是我的问题:

我有以下宏:

def using[A <: { def close(): Unit }, B](resource: A)(f: A => B) = macro usingImpl[A, B]

def usingImpl[A <: { def close(): Unit }, B](c: Context)(resource: c.Expr[A])(f: c.Expr[A => B]): c.Expr[B] = {

  import c.universe._


  f.tree match {
    case Function(params, body) =>
      //val ValDef(modifiers, name, tpt, _) = params.head
      c.Expr[B](
        Block(
          List(
            //ValDef(modifiers, name, tpt, resource.tree)
            ValDef(params.head.symbol, resource.tree)
          ),
          body
        )
      )

    case _: Select =>
      reify {
        val res = resource.splice
        try {
          f.splice(res)
        } finally …
Run Code Online (Sandbox Code Playgroud)

scala scala-macros

6
推荐指数
1
解决办法
414
查看次数

从SBT项目中的宏读取资源

假设我有一个包含三个子项目的Scala项目,文件如下:

foo/src/main/scala/Foo.scala
foo/src/main/resources/foo.txt

bar/src/main/scala/Bar.scala
bar/src/main/resources/bar.txt

baz/src/main/scala/Baz.scala
baz/src/main/resources/baz.txt
Run Code Online (Sandbox Code Playgroud)

Foo.scala 包含一个读取给定路径资源的简单宏:

import scala.language.experimental.macros
import scala.reflect.macros.Context

object Foo {
  def countLines(path: String): Option[Int] = macro countLines_impl

  def countLines_impl(c: Context)(path: c.Expr[String]) = {
    import c.universe._

    path.tree match {
      case Literal(Constant(s: String)) => Option(
        this.getClass.getResourceAsStream(s)
      ).fold(reify(None: Option[Int])) { stream =>
        val count = c.literal(io.Source.fromInputStream(stream).getLines.size)
        reify(Some(count.splice))
      }
      case _ => c.abort(c.enclosingPosition, "Need a literal path!")
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

如果资源可以打开,则countLines返回行数; 否则它是空的.

另外两个Scala源文件只调用此宏:

object Bar extends App {
  println(Foo.countLines("/foo.txt"))
  println(Foo.countLines("/bar.txt"))
  println(Foo.countLines("/baz.txt"))
}
Run Code Online (Sandbox Code Playgroud)

和:

object Baz extends …
Run Code Online (Sandbox Code Playgroud)

scala classpath maven sbt scala-macros

6
推荐指数
1
解决办法
984
查看次数

是否可以使用可变参数定义宏,并为每个参数获取一个类型?

以下是一个明显的可变函数:

def fun(xs: Any*) = ???
Run Code Online (Sandbox Code Playgroud)

我们可以用类似的方式定义一个宏:

def funImpl(c: Context)(xs: c.Expr[Any]*) = ???

fun(1,"1",1.0)
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,所有参数都被输入为Any.实际上,编译器在编译时知道类型,但是将它隐藏起来.是否有可能得到的参数列表,并在宏它们的类型?

macros scala scala-2.10 scala-macros

6
推荐指数
1
解决办法
562
查看次数

如何获取Scala函数的参数/返回类型?

我有一个函数,并希望获取其参数类型和返回类型以供在Scala宏中使用.

scala> val fn = (a: String, b: Double) => 123
fn: (String, Double) => Int = <function2>

scala> fn.getClass
res1: Class[_ <: (String, Double) => Int] = class $anonfun$1
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,参数类型和返回类型已经在两行打印,但我不知道如何访问它们.即使toString我会坚持的<function2>,并class $anonfun$1在部分权=标志-否则有点难看字符串解析的可能已经完成.

我发现MethodSymbolApi提供了一种方法来提取方法的信息,但似乎这可能对这种特殊情况没有帮助.

我目前正在研究AST解析(作为其中的一部分scala.meta)来提取信息,但我认为这个问题看起来很基本,可以被标准反射库覆盖,尽管我没有在那里找到我想要的东西. .有任何想法吗?

根据@ johanandren的回答编辑:

我还没有找到一种更简洁的方法从TypeTag/Type中提取它们,但这确实有效.:)

scala> val fn = (a: String, b: Double) => 123
scala> import scala.reflect.runtime.{universe => ru}
scala> def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T]
scala> getTypeTag(fn).tpe.toString.split(" => ")
res179: Array[String] = Array((String, …
Run Code Online (Sandbox Code Playgroud)

reflection scala anonymous-function scala-macros

6
推荐指数
1
解决办法
3010
查看次数

如何获取传递给 Scala 宏的参数的运行时值?

我有一个表面上很简单的宏观问题,我已经用头撞了几个小时,但没有运气。也许有更多经验的人可以提供帮助。

我有以下宏:

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

object MacroObject {
  def run(s: String): Unit =
    macro runImpl

  def runImpl(c: Context)(s: c.Tree): c.Tree = {
    import c.universe._
    println(s)    // <-- I need the macro to know the value of s at compile time
    q"()"
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是:我希望宏知道s传递给它的值——不是 AST s,而是s它本身的值。具体来说,我希望它具有这种行为:

def runTheMacro(str: String): Unit = MacroObject.run(str)

final val HardCodedString1 = "Hello, world!"
runTheMacro(HardCodedString1)    // the macro should print "Hello, world!"
                                 // to the console during macro expansion …
Run Code Online (Sandbox Code Playgroud)

macros scala scala-macros scala-quasiquotes scala-reflect

6
推荐指数
1
解决办法
528
查看次数

如何使用宏在 Dotty 中生成一个类?

是否可以在 Dotty, Scala 3 中生成一个带有宏的新类?

兹拉亚

annotations scala metaprogramming dotty scala-macros

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

如何在 Scala 3 宏中创建泛型类型的实例?

我正在将宏从 Scala 2 移植到 Scala 3。作为其工作的一部分,Scala 2 宏使用默认构造函数创建泛型类型的实例。在 Scala 2 中使用准引用很容易做到这一点,但我在 Scala 3 宏上遇到了困难。这是迄今为止我最好的方法:

import scala.quoted.*

inline def make[A <: AnyRef]: A = ${ makeThat[A] }

private def makeThat[A <: AnyRef : Type](using Quotes): Expr[A] =
  import quotes.reflect.*

  '{ new A().asInstanceOf[A] }
Run Code Online (Sandbox Code Playgroud)

如果没有.asInstanceOf[A],编译器会发出错误消息:

[error] -- [E007] Type Mismatch Error: ...
[error] 17 |  '{ new A() }
[error]    |     ^^^^^^^
[error]    |Found:    Object
[error]    |Required: A
[error]    |
[error]    |where:    A is a type in method makeThat with …
Run Code Online (Sandbox Code Playgroud)

scala metaprogramming scala-macros scala-3

6
推荐指数
1
解决办法
501
查看次数

Scala 3 宏中的显式类型转换

我在 Scala 3 中定义了以下特征:

\n
trait A[T <: Tuple]\n
Run Code Online (Sandbox Code Playgroud)\n

然后,我使用 Scala 3 宏创建具有此特征的对象,对元组的实际类型执行进一步检查T;特别是,我想检查元组的所有类型(T_1,\xe2\x80\xa6,T_nT是否是另一个给定类型的子类型B

\n
trait B\nprivate def allSubtypesOfB[T <: Tuple: Type](using quotes: Quotes): Boolean = {\n    import quotes.reflect.*\n    case '[Nothing] => false // I don't want nothing to be in T\n    case '[head *: tail] if TypeRepr.of[head] <:< TypeRepr.of[B] => allSubtypesOfB[tail]\n    case '[EmptyTuple] => true\n    case _ => false\n}\n\ninline def createA[T <: Tuple] = ${ createAImpl[T] }\nprivate def createAImpl[T …
Run Code Online (Sandbox Code Playgroud)

generics scala tuples scala-macros scala-3

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