[英]Can Scala macros be defined inside a class (as methods of that class)?
I need Scala macros (reify, quasiquote, macro impl) for my Scala assertions library. 我的Scala断言库需要Scala宏(reify,quasiquote,macro impl)。
I want to be able to do this: 我希望能够做到这一点:
object1.assertEquals(object2) // success: object1 = object2
Or like this: 或像这样:
3.assertEquals(1 + 1) // failure: 1 + 1 /= 3
Can Scala macros be defined inside an implicit class? 可以在隐式类中定义Scala宏吗?
//ed : write package // ed:写包
package so
trait AssertEquals[T, V] {
def assertEquals(t: T, v: V): Boolean
}
object AssertEquals {
implicit def assertEquals[T, V]: AssertEquals[T, V] = macro impl[T, V]
implicit class WithAssertEquals[T](t: T) {
def assertEquals[V](v: V)(implicit assertEquals: AssertEquals[T, V]): Boolean = assertEquals.assertEquals(t, v)
}
def impl[T: c.WeakTypeTag, V: c.WeakTypeTag](c: Context) = {
import c.universe._
val _t = c.weakTypeOf[T]
val _v = c.weakTypeOf[V]
//edit 2 : use symbolOf instead typeOf
q"""
{
new ${symbolOf[so.AssertEquals[_, _]]}[${_t},${_v}]{
def assertEquals(t: ${_t}, v: ${_v}): Boolean = t == v
}
}
"""
}
}
//test //测试
import AssertEquals.WithAssertEquals
assert(1.assertEquals(2) == false)
assert(2.assertEquals(2) == true)
assert("a".assertEquals("a") == true)
assert("a".assertEquals("b") == false)
assert("a".assertEquals(1) == false)
The implementation has to be in an object or a macro bundle, but the method that is implemented by the macro can be in an implicit class. 该实现必须在对象或宏包中,但是由宏实现的方法可以在隐式类中。 Notice
val self = q"${c.prefix}.self"
that is needed to get the reference to the object that is wrapped by the implicit class. 请注意,需要使用
val self = q"${c.prefix}.self"
才能获得对由隐式类包装的对象的引用。
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
object assertions {
implicit class AssertEquals[T](val self: T) extends AnyVal {
def assertEquals(other: T): Unit = macro AssertionMacros.assertEquals[T]
}
object AssertionMacros {
def assertEquals[T](c: Context)(other: c.Tree): c.Tree = {
import c.universe._
val self = q"${c.prefix}.self"
q"_root_.scala.Predef.assert($self == $other)"
}
}
}
Usage: 用法:
scala> import assertions._
import assertions._
scala> "foo" assertEquals "foo"
scala> "foo" assertEquals "bar"
java.lang.AssertionError: assertion failed
at scala.Predef$.assert(Predef.scala:151)
... 43 elided
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.