2012-07-09 228 views
12

在Scala中使用SBT工具鏈時,是否可以編寫一個任務來讀取項目源代碼的特殊部分,以便在編譯時生成scala代碼。使用Scala代碼生成

任何想法,甚至文章/教程呢?我正在尋找類似於模板哈斯克爾的東西。

+0

是的,這是可能的。我很確定有插件可以做到這一點。你看過現有插件列表嗎? – 2012-07-09 20:17:38

回答

13

treehugger.scala是設計用於代碼生成的庫。

import treehugger.forest._ 
import definitions._ 
import treehuggerDSL._ 

val tree: Tree = Predef_println APPLY LIT("Hello, world!") 

println(tree) 
println(treeToString(tree)) 

上面代碼打印兩行:

Apply(Ident(println),List(Literal(Constant(Hello, world!)))) 
println("Hello, world!") 

treehugger不會產生AST,但非符合scalac的AST。

+5

只是爲了澄清:treehugger =源代碼生成;宏= AST代。前者是低科技,實際上可以是優勢:) – retronym 2012-07-09 19:20:47

+0

@EugeneYokota,計劃在Scala 2.10附近發佈一個版本嗎? – jeslg 2012-07-27 11:42:11

7

Scala 2.10爲宏提供了實驗性的支持,這些宏同樣也是複雜的編譯時代碼生成。有關更多詳細信息,請參閱here

有賈森Zaugg的的macrocosm Git倉庫中一些有趣的例子,在LINQ樣的方式來表達的SLICK庫,是ScalaQuery SQL DSL實現類型安全的數據庫(和收集)查詢的演變。

而這個示例中,從斷言expecty庫:

import org.expecty.Expecty 

case class Person(name: String = "Fred", age: Int = 42) { 
    def say(words: String*) = words.mkString(" ") 
} 

val person = Person() 
val expect = new Expecty() 

... 
val word1 = "ping" 
val word2 = "pong" 

expect { 
    person.say(word1, word2) == "pong pong" 
} 

產量:

java.lang.AssertionError: 

person.say(word1, word2) == "pong pong" 
|  | |  |  | 
|  | ping pong false 
|  ping pong 
Person(Fred,42) 
+0

他們什麼時候有望成爲一個完整的功能? – Lanbo 2012-07-09 18:21:13

+1

我相信編譯器開發團隊正在2.10試用它們,看看社區發現它們有多麼有用。目前的想法(就在我幾個星期前閱讀內部郵件列表的最後一次)是,他們仍然沒有把它們視爲試驗性的可能性。但是,如果社區支持非常積極,我想他們會被採納。雖然這個網站上還有其他人可能會給你一個更明確的答案。 – 2012-07-09 18:26:14

+1

它們看起來非常像Template Haskell,並且被廣泛使用。儘管很多情況下Scala可以在沒有這個的情況下很好地服務(比如複雜類的自動擴展)。但爲了我的目的,在編譯前預處理資產,這是合適的。 – Lanbo 2012-07-09 18:29:41