2016-03-23 27 views
0

Scala hakemler kitaplığım için Scala makrolarına (yeniden adlandır, sorgulama, makro impl) ihtiyacım var. Can Scala makroları bir sınıf içinde tanımlanmalıdır (bu sınıfın yöntemleri olarak)?


Bunu yapabilmek istiyorum:
object1.assertEquals(object2) // success: object1 = object2 

Ya da böyle

:

3.assertEquals(1 + 1) // failure: 1 + 1 /= 3 

Scala makro örtük bir sınıf içinde tanımlanmış edilebilir mi?

+0

Evet, bir def makro sadece bir yöntem çağırma olduğunu. Uygulamada gördüğünüz önek farklı görünecektir. –

+0

@ som-snytt - "Uygulamada gördüğünüz önek farklı görünecek" ile ne demek istiyorsunuz? –

+0

@ som-snytt - Eğer nesnenin kendisini, "bu", makroya aktarılmak istenirse, sadece "$ $" yapıp bunu diğer Ağaçlar gibi bir Ağaç olarak mı kullanırım? –

cevap

0
uygulaması, bir nesne ya da bir makro demeti, ancak makro tarafından uygulanan yöntemde olmak zorundadır

can örtük bir sınıfta olmak. Bildirim, örtük sınıf tarafından sarılmış nesneye başvurmak için gerekli olan 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)" 
    } 
    } 
} 

Kullanımı:

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 
+0

Bu daha temiz bir uygulamadır. Özellikle "kendi kendini" nasıl ifade ettiğinizi özellikle beğeniyorum, böylece makro, sınıfa aitmiş gibi hissettiriyor. En iyi cevap. –

1

// ed: yazma paketi

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) 
+0

Paket demek istiyor musunuz? nesne "yani"? Çünkü paketi "o kadar" yarattım ve içine koydum ve işe yaramadı. –

+0

bulunamadı: type AssertEquals [error] assert (1.assertEquals (2) == false) –

+0

'package so' –

İlgili konular