2012-07-09 144 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