如何使用scala宏打印变量名和值? [英] how to print variable name and value using a scala macro?

查看:123
本文介绍了如何使用scala宏打印变量名和值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我确信有一种更优雅的方式来编写以下宏来打印变量的名称和值:

I am sure there is a more elegant way of writing the following macro which prints the name and value of a variable:

def mprintx(c: Context)(linecode: c.Expr[Any]): c.Expr[Unit] = {
    import c.universe._

    val namez = (c.enclosingImpl match {
        case ClassDef(mods, name, tparams, impl) =>
            c.universe.reify(c.literal(name.toString).splice)
        case ModuleDef(mods, name, impl) =>
            c.universe.reify(c.literal(name.toString).splice)
        case _ => c.abort(c.enclosingPosition, "NoEnclosingClass")
    }).toString match {
        case r_name(n) => n
        case _         => "Unknown?"
    }

    val msg = linecode.tree.productIterator.toList.last.toString.replaceAll("scala.*\\]", "").replaceAll(namez+"\\.this\\.", "").replaceAll("List", "")
    reify(myPrintDln(c.Expr[String](Literal(Constant(msg))).splice+" ---> "+linecode.splice))
}

def myPrintIt(linecode: Any) = macro mprintx

由以下程序调用:

object Zabi2 extends App {
val l = "zab"
val kol = 345
var zub = List("2", 89)
val zubi = List(zub,l,kol)

printIt(l)
printIt(l, kol, (l, zub),zubi)
}

打印:

l ---> zab
(l, kol, (l, zub), zubi) ---> (zab,345,(zab,List(2, 89)),List(List(2, 89), zab, 345))

预先感谢您的帮助.

推荐答案

这是一个打印表达式及其值的宏:

Here is a macro to print expressions and their values:

package mymacro

import scala.annotation.compileTimeOnly
import scala.language.experimental.macros
import scala.reflect.macros.whitebox

@compileTimeOnly("DebugPrint is available only during compile-time")
class DebugPrint(val c: whitebox.Context) {
  import c.universe._

  def impl(args: c.Expr[Any]*): c.Tree = {
    val sep = ", "
    val colon = "="
    val trees = args.map(expr => expr.tree).toList
    val ctxInfo = s"${c.internal.enclosingOwner.fullName}:${c.enclosingPosition.line}: "
    val treeLits = trees.zipWithIndex.map {
      case (tree, i) => Literal(Constant((if (i != 0) sep else ctxInfo) + tree + colon))
    }
    q"""
      System.err.println(StringContext(..$treeLits, "").s(..$trees))
    """
  }
}

@compileTimeOnly("DebugPrint is available only during compile-time")
object DebugPrint {
  def apply(args: Any*): Any = macro DebugPrint.impl
}

示例:

package myapp

import mymacro.DebugPrint

case class Person(name: String, age: Int)

object Main extends App {
  val x = 5
  val y = "example"
  val person = Person("Derp", 20)

  DebugPrint(x, y, person, person.name, person.age)

  def func()  = {
    val x = 5
    val y = "example"
    val person = Person("Derp", 20)
    DebugPrint(x, y, person, person.name, person.age)
  }

  func()
}

输出:

myapp.Main.<local Main>:12: Main.this.x=5, Main.this.y=example, Main.this.person=Person(Derp,20), Main.this.person.name=Derp, Main.this.person.age=20
myapp.Main.func:18: x=5, y=example, person=Person(Derp,20), person.name=Derp, person.age=20

适用于 Scala 2.12.12.

Works well with scala 2.12.12.

这篇关于如何使用scala宏打印变量名和值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆