Scala宏打印代码?
我想做这样的事情:
def assuming[A](condition: => Boolean)(f: => A): A = { require(condition,/* print source-code of condition */) f } 样品用法: def fib(n: Int) = n match { // yes,yes,I know this is not efficient case 0 => 0 case 1 => 1 case i => assuming(i > 0) { fib(i-1) + fib(i-2) } } 现在,例如,如果你调用fib(-20),我希望它抛出异常并带有断言失败的消息:-20> 0或断言失败:i> 0 解决方法
Dude,是不是断言宏的一个基本用例,你学习如何使用宏?
嗯,这也是我的想法. 通过我的另一个答案中的“glean snippets”,我的意思是specs2做了in its s2 macro. 或者,您可以执行任意表示,如in my variant rip-off of expecty. 我以为我会把你的例子输入REPL,有几行.毕竟,您只是尝试从与表示条件的树对应的源打印片段. 什么可以更容易? 当然,在-Yrangepos下更容易,但我们可以假设位置. 在失去兴趣之前,我愿意分享我的成就. 人们(例如,paulp,谁是vox paulpuli)希望树有附件代表“我在键盘上键入的来源”,因为,你知道,也许我想要它用于消息或弄清楚用户尝试的是什么完成. 看起来谓词p没有范围位置.所以另一个想法是我们知道宏应用程序的开始,这是第二个参数列表的paren,因此通过源向后工作,匹配第一个参数列表的结束列表是可行的. 请注意,showCode没有帮助,因为对于像10< 5它显示虚假,整齐折叠. object X { import reflect.macros.blackbox.Context def impl[A: c.WeakTypeTag](c: Context)(p: c.Expr[Boolean])(body: c.Expr[A]) = { import c.universe._ def treeLine(t: Tree): String = lineAt(t.pos) def lineAt(pos: Position): String = if (pos.isRange) pos.lineContent.drop(pos.column - 1).take(pos.end - pos.start + 1) else "???" val msg = if (p.tree.pos.isRange) { // oh,joy treeLine(p.tree) } else { /* Console println s"content ${p.tree.pos.lineContent}" Console println s"column ${p.tree.pos.column}" // alas,that's the column of the point of the top of the tree,e.g.,< in "a < b". val len = body.tree.pos.start - p.tree.pos.start p.tree.pos.lineContent drop (p.tree.pos.column - 1) take len */ // OK,I get it: positions are a big mystery. Make woo-woo ghost noises. // What we do know is the start of the apply,which must have a close paren or brace in front of it to match: // apply(condition)(body) showCode(p.tree) } q"require($p,$msg) ; $body" } def x[A](p: Boolean)(body: =>A): A = macro X.impl[A] } 我突然想到以这种方式获得笨拙的位置: object X { import reflect.macros.blackbox.Context def impl(c: Context)(p: c.Expr[Boolean]) = { import c.universe._ def lineAt(pos: Position): String = if (pos.isRange) pos.lineContent.drop(pos.column - 1).take(pos.end - pos.start + 1) else "???" val msg = lineAt(c.macroApplication.pos) // oh,joy q"require($p,$msg) ; new { def apply[A](body: =>A): A = body }" } def x(p: Boolean): { def apply[A](body: =>A): A } = macro X.impl } 这与使用率x(10 <5)(println(“hi”))接近:要求失败:(10 <5)(p.错误的保证金. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |