如何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 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) 我想使用 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 中翻译这段代码?
我是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宏做到这一点?或者有另一种方法来实现这一目标吗?
我想得到一个宏的调用类,但我的代码不起作用:
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)
在此先感谢您的帮助.
在宏内部,我如何要求编译器推断构造树的类型?我只找到Context.typeCheck,但它只检查类型但不返回结果.
我有一个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) 特定
trait A[T]
class B[T] extends A[Option[T]]
Run Code Online (Sandbox Code Playgroud)
在宏中,我可以看到它A是超类型B并且B是子类型A,但缺少类型参数如何匹配的细节.
我怎样才能获得完整的extends A[Option[T]]信息?
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
我正在尝试构建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) scala ×10
scala-macros ×10
macros ×3
scala-2.10 ×3
scala-3 ×3
case-class ×1
dsl ×1
implicit ×1
java ×1
reflection ×1
shapeless ×1
typeclass ×1