我有以下宏:如何在Scala編譯時檢查一些T是否是case類?
package macros
import scala.reflect.macros.blackbox.Context
object CompileTimeAssertions {
def mustBeCaseClass[T]: Unit =
macro CompileTimeAssertionsImpl.mustBeCaseClass[T]
}
object CompileTimeAssertionsImpl {
def mustBeCaseClass[T: c.WeakTypeTag](c: Context): c.Expr[Unit] = {
import c.universe._
val symbol = c.weakTypeTag[T].tpe.typeSymbol
if (!symbol.isClass || !symbol.asClass.isCaseClass) {
c.error(c.enclosingPosition, s"${symbol.fullName} must be a case class")
}
reify(Unit)
}
}
它工作時不參與仿製藥,但是當他們失敗:
import macros.CompileTimeAssertions._
import org.scalatest.{Matchers, WordSpec}
case class ACaseClass(foo: String, bar: String)
class NotACaseClass(baz: String)
class MacroSpec extends WordSpec with Matchers {
"the mustBeCaseClass macro" should {
"compile when passed a case class" in {
mustBeCaseClass[ACaseClass]
}
"not compile when passed a vanilla class" in {
// mustBeCaseClass[NotACaseClass] // fails to compile as expected.
}
"compile when working with generics" in {
// class CaseClassContainer[T] { mustBeCaseClass[T] } // fails to compile.
// new CaseClassContainer[ACaseClass]
}
}
}
編譯器錯誤都是我的
MacroSpec.CaseClassContainer.T must be a case class
我想知道當CaseClassContainer被實例化時T是什麼。這甚至有可能嗎?如果你能提供一個例子嗎?
在此先感謝。
不幸的是,你試圖做的事情是無法用這種方式實現的。 Def宏在你編寫它們的地方立即展開,因此在展開的時候,你所看到的所有內容都是T. –
但是,如果你可以改變你的方法來結合類型類,你可能會得到某個地方。也就是說:你可以有一個'CaseClass [T]'類型的類,然後你可以說'class CaseClassContainer [T:CaseClass]'。查看https://github.com/scalamacros/macrology201/tree/part2,瞭解如何編寫這樣的宏。 –
謝謝尤金!請隨意將這些複製並粘貼到答案中,並將其標記爲正確。不是答案,也許比我13分鐘前的地方要好很多。 –