Scala 宏:从宏发出理解
Scala macros: Emit for comprehensions from macros
试图从黑盒宏发出一个 for yield
块,但我无法理解如何使用有效语法创建块。
因此 source
下面是一个硬编码的参数名称,因为此块稍后将插入到将具有匹配参数名称的方法中。 params
只是 params: Seq[c.universe.ValDef]
,包含 case class
个字段。
def extract(source: Source): Option[CaseClass] = { ... }
val extractors = accessors(c)(params) map {
case (nm, tpe) => {
val newTerm = TermName(nm.toString + "Opt")
q"""$newTerm <- DoStuff[$tpe].apply("$nm", source)"""
}
}
val extractorNames = accessors(c)(params) map {
case (nm, tpe) => TermName(nm.toString + "Opt")
}
这基本上是采用 case class
,并输出一个 for yield black,基本上从理解中重新创建案例 class。
name: Type
形式的 case class 中的每个字段都被转换为一组提取器,如果 for 理解成功,这些提取器会返回相同的 case class 实例。
case class Test(id: Int, text: String)
将被宏转换为以下内容,其中 Extract
只是一种类型 class 而 Extract.apply[T : Extract]
只是具体化与 implicitly[Extract[T]]
绑定的上下文:
for {
idOpt <- Extract[Int].apply("id", source): Option[Int]
textOpt <- Extract[String].apply("text", source): Option[String]
} yield Test(idOpt, textOpt)
问题在于必须引用内部的 yield 表达式并输出 a <- b
块。
def extract(source: Source): Option[$typeName] = {
for {(..$extractors)} yield $companion.apply(..$extractorNames)
}
错误是 ';' expected but '<-' found
,这很明显,因为 a <- b
本身是无效的 Scala。生成和准引用表达式块的正确方法是什么才能使上述内容起作用?
Here 是所有不同种类的准引号的列表。
在那里您可以看到,要表达 a <- b
语法,您需要 fq
插值器。
所以该代码可能会变成:
val extractors = accessors(c)(params) map {
case (nm, tpe) => {
val newTerm = TermName(nm.toString + "Opt")
fq"""$newTerm <- DoStuff[$tpe].apply("$nm", source)"""
}
}
然后使用普通插值器:
q"for (..$extractors) yield $companion.apply(..$extractorNames)"
试图从黑盒宏发出一个 for yield
块,但我无法理解如何使用有效语法创建块。
因此 source
下面是一个硬编码的参数名称,因为此块稍后将插入到将具有匹配参数名称的方法中。 params
只是 params: Seq[c.universe.ValDef]
,包含 case class
个字段。
def extract(source: Source): Option[CaseClass] = { ... }
val extractors = accessors(c)(params) map {
case (nm, tpe) => {
val newTerm = TermName(nm.toString + "Opt")
q"""$newTerm <- DoStuff[$tpe].apply("$nm", source)"""
}
}
val extractorNames = accessors(c)(params) map {
case (nm, tpe) => TermName(nm.toString + "Opt")
}
这基本上是采用 case class
,并输出一个 for yield black,基本上从理解中重新创建案例 class。
name: Type
形式的 case class 中的每个字段都被转换为一组提取器,如果 for 理解成功,这些提取器会返回相同的 case class 实例。
case class Test(id: Int, text: String)
将被宏转换为以下内容,其中 Extract
只是一种类型 class 而 Extract.apply[T : Extract]
只是具体化与 implicitly[Extract[T]]
绑定的上下文:
for {
idOpt <- Extract[Int].apply("id", source): Option[Int]
textOpt <- Extract[String].apply("text", source): Option[String]
} yield Test(idOpt, textOpt)
问题在于必须引用内部的 yield 表达式并输出 a <- b
块。
def extract(source: Source): Option[$typeName] = {
for {(..$extractors)} yield $companion.apply(..$extractorNames)
}
错误是 ';' expected but '<-' found
,这很明显,因为 a <- b
本身是无效的 Scala。生成和准引用表达式块的正确方法是什么才能使上述内容起作用?
Here 是所有不同种类的准引号的列表。
在那里您可以看到,要表达 a <- b
语法,您需要 fq
插值器。
所以该代码可能会变成:
val extractors = accessors(c)(params) map {
case (nm, tpe) => {
val newTerm = TermName(nm.toString + "Opt")
fq"""$newTerm <- DoStuff[$tpe].apply("$nm", source)"""
}
}
然后使用普通插值器:
q"for (..$extractors) yield $companion.apply(..$extractorNames)"