2017-09-01 33 views
1

下應該顯示的問題:重新安裝類型參數在宏擴展

class Container[A](val xs: List[A]) { 
    def foo(fun: A => A)(implicit ord: Ordering[A]): List[A] = 
    macro ContainerMacros.fooImpl // how to pass `xs`? 
} 

object ContainerMacros { 
    def fooImpl(c: blackbox.Context) 
      (fun: c.Expr[Nothing => Any]) 
      (ord: c.Expr[Ordering[_]]): c.Expr[List[Nothing]] = { 
    import c.universe._ 
    reify { 
     // val cont = c.prefix.splice.asInstanceOf[Container[_]] 
     // cont.xs.map(fun.splice).sorted(ord.splice) 
     ??? 
    } 
    } 
} 

也就是說,似乎沒有辦法爲類型參數添加AfooImpl(如果我這樣做,編譯器抱怨)。因此,我必須將其刪除,但問題是如何使reify中的內容以預期的方式工作,即如何重新引入缺少的類型參數A

下面是一個嘗試:

def fooImpl(c: blackbox.Context) 
      (fun: c.Expr[Nothing => Any]) 
      (ord: c.Expr[Ordering[_]]): c.Expr[List[Nothing]] = { 
    import c.universe._ 
    reify { 
    val ext = c.prefix.splice.asInstanceOf[ExtensionTest[_]] 
    import ext.{A1 => A} 
    val extC = ext  .asInstanceOf[ExtensionTest[A]] 
    val funC = fun.splice.asInstanceOf[A => A] 
    val ordC = ord.splice.asInstanceOf[Ordering[A]] 
    val xs = extC.xs.asInstanceOf[List[A]] // computer says no 
    xs.map(funC).sorted(ordC) 
    } 
} 

xs.map(funC)不會與這些傳說中的scalac錯誤消息之一工作:

Error:(27, 16) type mismatch; 
found : _$2 => Any where type _$2 
required: Any => ? 
     xs.map(funC).sorted(ordC) 

回答

1

其實答案多虧通過斯卡拉@edmundnoble Gitter頻道:

您可以添加type para在impl調用中,因此可以將AContainer傳遞給宏擴展:

class Container[A](val xs: List[A]) { 
    def foo(fun: A => A)(implicit ord: Ordering[A]): List[A] = 
    macro ContainerMacros.fooImpl[A] 
} 

object ContainerMacros { 
    def fooImpl[A](c: blackbox.Context) 
       (fun: c.Expr[A => A]) 
       (ord: c.Expr[Ordering[A]]) 
       (implicit t: c.WeakTypeTag[A]): c.Expr[List[A]] = { 
    import c.universe._ 
    reify { 
     val extC = c.prefix.splice.asInstanceOf[Container[A]] 
     val funC = fun.splice 
     val ordC = ord.splice 
     val xs = extC.xs 
     xs.map(funC).sorted(ordC) 
    } 
    } 
}