我想編寫一個Scala宏,它將一個case類的實例作爲參數。所有可以傳遞給宏的對象都必須實現特定的標記特徵。傳遞給Scala宏的內省參數
如下片段展示標記性狀和兩個示例的情況下的類實施它:
trait Domain
case class Country(id: String, name: String) extends Domain
case class Town(id: String, longitude: Double, latitude: Double) extends Domain
現在,我想使用宏,以避免運行時反射和其螺紋不安全的沉重寫以下代碼:
object Test extends App {
// instantiate example domain object
val myCountry = Country("CH", "Switzerland")
// this is a macro call
logDomain(myCountry)
}
宏logDomain
在不同的項目實施,類似如下:
object Macros {
def logDomain(domain: Domain): Unit = macro logDomainMacroImpl
def logDomainMacroImpl(c: Context)(domain: c.Expr[Domain]): c.Expr[Unit] = {
// Here I would like to introspect the argument object but do not know how?
// I would like to generate code that prints out all val's with their values
}
}
宏的目的應該是生成的代碼 - 在運行時 - 輸出給定對象的所有值(id
和name
),並將它們打印如下圖所示:
id (String) : CH
name (String) : Switzerland
要做到這一點,我會動態檢查傳入的類型參數並確定其成員(vals)。然後我將不得不生成代表創建日誌輸出的代碼的AST。無論實現標記特徵「Domain」的特定對象傳遞給宏,宏應該工作。
此時我迷路了。如果有人能給我一個出發點或者指點我一些文檔,我將不勝感激。我相對較新的Scala,並沒有在Scala API文檔或宏指南中找到解決方案。
你打我5分鐘! :) –
非常感謝您的詳細解答!你的例子完全符合我的要求。今晚我會嘗試一下。你的解決方案的好處是使用類型參數和WeakTypeTag,它使代碼完全通用。它應該適用於任何實施「域」的案例類。 – MontChanais