Я хотел бы запрограммировать макрос Scala, который принимает экземпляр класса case в качестве аргумента. Все объекты, которые могут быть переданы макросу, должны реализовать конкретный признак маркера.
В следующем фрагменте показан маркерный признак и два примерных класса, реализующих его:
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 with their values
}
}
Цель макроса должна заключаться в создании кода, который во время выполнения выводит все значения (id
и name
) данного объекта и печатает их, как показано ниже:
id (String) : CH
name (String) : Switzerland
Чтобы достичь этого, мне пришлось бы динамически проверять аргумент переданного типа и определять его члены (vals). Тогда мне пришлось бы генерировать AST, представляющий код, который создает выход журнала. Макрос должен работать независимо от того, какой конкретный объект реализует маркерный признак "Домен" передается макросу.
В этот момент я проиграл. Я был бы признателен, если бы кто-то мог дать мне отправную точку или указать мне какую-то документацию? Я относительно новичок в Scala и не нашел решения в документах API Scala API или Макро.