2015-04-28 29 views
0

鑑於以下類型的寫作宏:爲正整數

sealed trait PosIntCheckResult 
case class LteZero(x: Int) extends PosIntCheckResult 
case object NotConstant extends PosIntCheckResult 

我試圖寫檢查給定Int是宏大於0

import reflect.macros.Context 

def getInt(c: Context)(value: c.Expr[Int]): Either[PosIntCheckResult, Int] = { 

    import c.universe._ 

    value.tree match { 
     case Literal(Constant(x)) => if (x > 0) Right(x) else Left(LteZero(x)) 
     case _     => Left(NotConstant) 
    } 
} 

Any顯示出來對於x值:

Test.scala:29: type mismatch; 
    found : Any 
    required: Int 
    case Literal(Constant(x)) => 
     if (x > 0) Right(x) else Left(LteZero(x)) 

我該如何獲得公司mpiler期望Int而不是Any

+0

除了文字,我幾乎看不到一個簡單的方法來檢查是否「Int」值是正值(例如'def foo(x:Int)=''在運行前難以檢查'x')。您可能想看看https://github.com/non/spire/blob/master/README.md – cchantep

+1

這是一種非主題,但您可能對我的博客文章感興趣[here](https:// meta .plasm.us/posts/2013/10/03/natural-vampires /)爲基於宏觀的解決類似問題。 –

+0

在scalatest論壇中有些相關的問題 - https://groups.google.com/forum/#!topic/scalatest-users/guIlCXHbgh8 –

回答

1

你只需要匹配的模式,其中xInt

case Literal(Constant(x: Int)) => //When using x here, it is an Int 

閱讀有關圖案類型和其他類型的模式在docs匹配匹配。

你也應該注意到你的宏需要返回一個Expr才能工作。您可以使用reify在每個case構建所需的Exprs。閱讀關於reifydef macroshere。我不知道爲什麼,這需要有一個宏觀的,但如果你只是學習技術,這樣的事情可能工作:

object Macros { 
    def getInt(value: Int): Either[PosIntCheckResult, Int] = macro getIntImpl 

    def getIntImpl(c: Context)(value: c.Expr[Int]): c.Expr[Either[PosIntCheckResult,Int]] = { 

     import c.universe._ 

     value.tree match { 
      case [email protected](Constant(const: Int)) if const > 0 => reify(Right(c.Expr[Int](x).splice)) 
      case [email protected](Constant(_: Int)) => reify(Left(LteZero(c.Expr[Int](x).splice))) 
      case _ => reify(Left(NotConstant)) 
     } 
    } 
} 
+0

但是這種方法使用'asInstanceOf'?這是編譯時檢查嗎? –

+0

像這樣的模式匹配不使用'asInstanceOf'。這是一種模式匹配語法。它在編譯時被檢查,並且只有當'x'是一個'Int'時纔會匹配該情況。 –

+0

但是[gist](https://gist.github.com/kevinmeredith/2575581c71e51c23da17)怎麼樣?我沒有閱讀JVM字節碼,但在指令中看到'instanceOf'。最後,這篇文章顯示'isInstanceOf' [here](http://stackoverflow.com/a/3785053/409976),不是嗎? –