我正在尝试在 dotty 中学习元编程。具体编译时间代码生成。我认为通过构建一些东西来学习是一种很好的方法。所以我决定制作一个 CSV 解析器,它将行解析为案例类。我想使用dotty宏来生成解码器
trait Decoder[T]{
def decode(str:String):Either[ParseError, T]
}
object Decoder {
inline given stringDec as Decoder[String] = new Decoder[String] {
override def decode(str: String): Either[ParseError, String] = Right(str)
}
inline given intDec as Decoder[Int] = new Decoder[Int] {
override def decode(str: String): Either[ParseError, Int] =
str.toIntOption.toRight(ParseError(str, "value is not valid Int"))
}
inline def forType[T]:Decoder[T] = ${make[T]}
def make[T:Type](using qctx: QuoteContext):Expr[Decoder[T]] = ???
}
Run Code Online (Sandbox Code Playgroud)
我已经为Int
&提供了基本的解码器String
,现在我正在寻找def make[T:Type]
方法的指导。如何T
在此方法中迭代案例类的参数列表?有没有推荐的方法或模式来做到这一点?
我正在尝试使用 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)