2013-04-17 43 views
3

我對Scala宏很新,並且正在嘗試編寫一個非常基本的DSL。Scala宏:構建一個匿名類

我有以下的Scala類:

abstract class SpecialFunction { 
    def apply(): Unit 
} 

及以下斯卡拉宏:

def mImpl(c: Context)(bodyBlock: c.Expr[Unit]): c.Expr[X] = 
    c.universe.reify { 
    new X(new SpecialFunction { 
     override def apply() { 
     bodyBlock.splice 
     } 
    }) 
    } 

def m(bodyBlock: Unit): X = macro mImpl 

到目前爲止好。例如,它可以讓我寫:

def example = m { 
    println("Hello, world") 
} 

這編譯爲:

def example = new X(new SpecialFunction { 
    override def apply() { 
    println("Hello, world") 
    } 
}) 

但這個提法不容許我有局部變量,在這樣一個「M塊」。例如,我不能寫:

def example = m { 
    val x = 7 
    println(x.toString) 
} 

在編譯時出現錯誤:

symbol value x does not exist in example 

不過,我想實現的是:

def example = new X(new SpecialFunction { 
    override def apply() { 
    val x = 7 
    println(x.toString) 
    } 
}) 

(我認爲我明白爲什麼會是這種情況:子表達式在傳遞給宏之前被評估,因此對x的引用無效)。

所以我的問題是這樣的:我怎樣才能得到上述工作? (I只想在宏定義的額外的代碼是「複製粘貼」繞在「M塊」的代碼,就象是在C++宏。)

任何幫助,將不勝感激:-)

+0

宏定義中似乎存在語法錯誤。 – axel22

+0

@ axel22我刪除了本不該去的支架 –

回答

1

您的輸出表達式保留對舊x符號的引用,但它應該是對新符號的引用。因此,您可以通過從Context應用resetLocalAttrs來重置樹中您想要重用的所有垃圾引用。

怎麼樣...?

def mImpl(c: Context)(bodyBlock: c.Expr[Unit]): c.Expr[X] = 
    c.universe.reify { 
    new X(new SpecialFunction { 
     override def apply() { 
     c.Expr[Unit](c.resetLocalAttrs(bodyBlock.tree)).splice 
     } 
    }) 
    } 

在此question,就可以讀取斯卡拉宏傢伙很好的解釋。

+0

它的工作原理!非常感謝 –