标签: scala-macros

Scala 3 TypeRepr 匹配更高种类的类型

如何TypeRepr在更高级的类型上正确地进行模式匹配?存在成功匹配类,但是当我尝试使用类型时,出现编译器错误unreducible application of higher-kinded type writetype.Foo to wildcard arguments

import scala.quoted.*

type Foo[X]
class Bar[X]

inline def writeType[T]: String = ${writeTypeImpl[T]}

def writeTypeImpl[T](using Type[T], Quotes): Expr[String] =
  import quotes.reflect.*
  val tpe = TypeRepr.of[T]
  val s = tpe.asType match
    //case '[Foo[?]] => "FooSuccess"
    case '[Bar[?]] => "BarSuccess"
    case _ => "Fail"

  Expr(s)
Run Code Online (Sandbox Code Playgroud)

scala scala-macros scala-3

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

使用 Scala 3 宏重写方法

我正在尝试使用 Scala 3 宏和 TASTY 重写方法。我想重写任何类型的任何方法。现在我从这个简单的案例开始。

我有一个测试基类:

class TestClass {
  def func(s: String) = "base"
}
Run Code Online (Sandbox Code Playgroud)

我想实现这一点,但是通过使用 TASTY,我发现不可能调用new A带有引号和拼接的泛型类型:

'{
    new TestClass() {
       override def func(s: String) = "override"
    }
}.asExprOf[A]
Run Code Online (Sandbox Code Playgroud)

我打印了上述代码的 AST,并且几乎成功地重新创建了它。问题是我无法调用new生成的类 - 我没有找到访问新类的符号或类型的方法。我也尝试Symbol.requiredClass()使用新名称,尽管它返回了一些符号,但在宏扩展期间出现错误,未找到该类。

我的问题是:

  • 是否可以在不显式调用:的new Class {}情况下派生自定义类型?
  • 是否ClassDef.copy注册一个可以帮助创建新实例的新名称?
  • 可以手动调用ClassDef创建类的实例吗?
  • Symbol.requiredClass即使之前没有定义,如何使用返回的符号,因为它会返回某些内容?

我创建的代码:

import scala.quoted.*

object NewClass {

  def newClassImpl[A: Type](e: Expr[A])(using Quotes): Expr[A] = {
    import quotes.reflect.*

    val typeRep = TypeRepr.of[A]

    val ret = typeRep.classSymbol.map(_.tree) match …
Run Code Online (Sandbox Code Playgroud)

scala scala-macros scala-3

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

如何在Scala3中编译并在运行时执行scala代码?

我想使用 Scala3 编译并执行在运行时以字符串形式给出的 Scala 代码。例如在 Scala 2 中我会使用 Reflection

import scala.reflect.runtime.universe as ru
import scala.tools.reflect.ToolBox
val scalaCode = q"""println("Hello world!")"""
val evalMirror = ru.runtimeMirror(this.getClass.getClassLoader)
val toolBox = evalMirror.mkToolBox()
toolBox.eval(scalaCode) //Hello world!
Run Code Online (Sandbox Code Playgroud)

如果我尝试在 Scala3 中运行这段代码,我会得到

Scala 2 macro cannot be used in Dotty. See https://dotty.epfl.ch/docs/reference/dropped-features/macros.html
To turn this error into a warning, pass -Xignore-scala2-macros to the compiler
Run Code Online (Sandbox Code Playgroud)

我如何在 Scala3 中翻译这段代码?

java macros scala scala-macros scala-3

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

scala宏:向类添加函数

我是scala宏的新手,我正在使用scala 2.10.0-RC3.

我想编写一个向类添加函数的宏.用法示例:

trait MyTrait {
  def addF = macro { /*add "def f = 3" to class*/ }
}

class MyClass extends MyTrait {
  addF //Adds the "def f" to MyClass
}

object Main {
  val t = new MyClass
  assert(t.f==3)
}
Run Code Online (Sandbox Code Playgroud)

我在以下场景中需要这个.我的第一次尝试没有使用宏但没有用,因为我不能继承两次相同的特性.

trait AddF[T] {
  def f(t: T) { /* ...do sthg ... */ }
}

class MyClass extends AddF[Int] with AddF[String]
Run Code Online (Sandbox Code Playgroud)

使用宏解决方案,我可以写

class MyClass extends MyTrait {
  addF[Int]()
  addF[String]()
}
Run Code Online (Sandbox Code Playgroud)

有没有办法用scala宏做到这一点?或者有另一种方法来实现这一目标吗?

reflection scala metaprogramming scala-2.10 scala-macros

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

得到电话课

我想得到一个宏的调用类,但我的代码不起作用:

def __CLASS__(c: Context) = {
    import c.universe._
    c.enclosingClass match {
    case ClassDef(mods, name, tparams, impl) =>
    c.universe.reify(println(
            "\n  mods "+c.literal(mods.toString).splice
            +"\n  name "+c.literal(name.toString).splice
            +"\n  tparams "+c.literal(tparams.toString).splice
            +"\n  impl "+c.literal(impl.toString).splice
            ))
    case _ => c.abort(c.enclosingPosition, "NoEnclosingClass")
    }
}
Run Code Online (Sandbox Code Playgroud)

在此先感谢您的帮助.

scala scala-2.10 scala-macros

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

在scala宏中推断一种树的类型

在宏内部,我如何要求编译器推断构造树的类型?我只找到Context.typeCheck,但它只检查类型但不返回结果.

macros scala scala-macros

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

如何在scala宏中构建动态序列?

我有一个scala宏,它输出嵌套的case类.我可以汇编使用reify创建的表达式片段,以编程方式构建嵌套的case类:

case class Foo(name: String)
case class Bar(foo: Foo)

def foo(name: String) = { 
  c.universe reify { 
    Foo(c.literal(name).splice)
  }
}

def bar(foo: Expr[Foo]) = {
  c.universe reify { 
    Bar(foo.splice)
  }
}

// output Bar(Foo("MyFoo"))
c.Expr( bar(foo("MyFoo").asInstanceOf[Expr[Foo]]).tree )
Run Code Online (Sandbox Code Playgroud)

除了令人讨厌的演员之外,事情很有效(我怎么能解决这个问题?).我被困的地方是当我希望宏输出一些case类时,它需要一个内部对象的集合,其大小根据marco在AST处理的内容而变化.

所以,如果我有一个接受foo序列的类:

 case class Baz(foos: Seq[Foo])
Run Code Online (Sandbox Code Playgroud)

我想做一些事情:

def baz(foos: Seq[Expr[Foo]]): Expr[Baz] = {
  val flipped: Expr[Seq[Foo]] = ???  // convert foos from Seq[Expr[Foo]] to Expr[Seq[Foo]]
  c.universe reify {
    Baz(flipped.splice)
  }
}

// now pack any number of Foos into an output Baz as …
Run Code Online (Sandbox Code Playgroud)

scala scala-2.10 scala-macros

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

在scala宏中,如何获取类的完整`extends`子句?

特定

trait A[T]
class B[T] extends A[Option[T]]
Run Code Online (Sandbox Code Playgroud)

在宏中,我可以看到它A是超类型B并且B是子类型A,但缺少类型参数如何匹配的细节.

我怎样才能获得完整的extends A[Option[T]]信息?

macros scala scala-macros

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

什么是避免无形的两个类型定义之间发生冲突的最佳方法

Shapeless有一个简洁的类型派生机制,允许您定义类型类并获得任何类型类的自动派生.

要将派生机制用作类型类的用户,可以使用以下语法

import MyTypeClass.auto._
Run Code Online (Sandbox Code Playgroud)

据我所知,它相当于

import MyTypeClass.auto.derive
Run Code Online (Sandbox Code Playgroud)

当您尝试在同一范围内尝试使用多个类型类时会出现问题.看起来Scala编译器只考虑了derive的最后一个定义,即使它的隐式参数有两个版本的函数"重载".

我可以通过几种方法来解决这个问题.我不会在这里列出它们,而是将它们标记为答案,您可以投票确认理智并提出任何更好的解决方案.

scala typeclass type-level-computation shapeless scala-macros

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

DSL提取案例类字段名称

我正在尝试构建DSL,但我遇到了一个问题:它适用于案例类,但我想知道提取案例类字段名称的最简单方法.我想到的一个想法是使用宏来丰富我的Case类的类型,但我不愿意.

trait QueryDSL[CC] {

  def meta: CC

  implicit object StringIsFieldType extends Field[CC, String] {
    def name = "FakeNAME"
  }

  implicit def implQuery[V](b: V): Query[CC] = new Query[CC](meta)
  implicit def implField[V](b: V)(implicit ev: Field[CC, V]): QueryField[CC, V] = new QueryField(ev)
}

case class Query[CC](meta: CC, clauses: List[Clause[_]] = Nil) {

  def setProperty[F](clause: CC ? Clause[F]): Query[CC] = copy(clauses = clause(meta) :: clauses)
}

trait Field[V, M] extends scala.AnyRef {
  def name: scala.Predef.String
}

abstract class Clause[V](val fieldName: String, value: V)
case …
Run Code Online (Sandbox Code Playgroud)

dsl scala implicit case-class scala-macros

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