Генерация кода с помощью Scala

При использовании инструментальной цепочки SBT в Scala, возможно ли написать задачу, которая будет читать особую часть исходного кода проекта для генерации scala-кода во время компиляции.

Любые идеи или даже статьи / руководства по этому поводу? Я ищу что-то похожее на Template Haskell.


person Lanbo    schedule 09.07.2012    source источник
comment
Да, это возможно. Я почти уверен, что для этого есть плагины. Вы просматривали список существующих плагинов?   -  person Daniel C. Sobral    schedule 10.07.2012


Ответы (3)


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, но несовместим с AST скалака.

person Eugene Yokota    schedule 09.07.2012
comment
Чтобы уточнить: treehugger = генерация исходного кода; макросы = генерация AST. Первый менее технологичен, что на самом деле может быть преимуществом :) - person retronym; 09.07.2012
comment
@EugeneYokota, не планируется ли выпуск Scala 2.10 поблизости? - person jeslg; 27.07.2012

Scala 2.10 имеет экспериментальную поддержку макросов, которые похожи на сложную генерацию кода во время компиляции. Дополнительные сведения см. здесь.

Есть несколько забавных примеров в репозитории git Джейсона Заугга macrocosm и SLICK, которая представляет собой эволюцию ScalaQuery SQL DSL, позволяющую выражать типобезопасные запросы к базам данных (и коллекциям) в LINQ-подобном виде.

И этот пример из библиотеки утверждений 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)
person Alex Wilson    schedule 09.07.2012
comment
Когда они, как ожидается, станут полнофункциональными? - person Lanbo; 09.07.2012
comment
Я считаю, что команда разработчиков компилятора тестирует их в версии 2.10, чтобы увидеть, насколько они полезны для сообщества. Текущее мнение (когда я последний раз читал список рассылки по внутренним устройствам несколько недель назад) заключается в том, что они все еще оставляют открытой возможность использовать их только как экспериментальные. Но если поддержка сообщества будет очень положительной, я думаю, они будут приняты. На этом сайте есть и другие люди, которые могут дать вам более точный ответ. - person Alex Wilson; 09.07.2012
comment
Они очень похожи на Template Haskell и широко используются. Хотя во многих случаях Scala может хорошо работать без этого (например, автоматическое расширение для сложных классов). Но для моей цели, предварительной обработки ресурсов при компиляции, это подходит. - person Lanbo; 09.07.2012

Недавно я провел небольшое исследование. Практически доступно 3 варианта:

  1. Строковые шаблоны.
  2. дерево Hugger
  3. Макросы Scala

Подробнее здесь: http://yefremov.net/blog/scala-code-generation/

person Dmitriy Yefremov    schedule 08.01.2015