Макросы Scala, где они используются?

Я только что заметил, что у Scala есть макросы, но я никогда не видел кода, который их использует. Они также сильно отличаются от макросов препроцессора C и тому подобного. Чтение обзор макросов, не похоже, что они предлагают что-то, что ранее не было возможно в Scala. Под заголовком мотивации есть список вещей, которые макросы включают:

  • виртуализация языка (перегрузка / переопределение семантики оригинальный язык программирования для обеспечения глубокого внедрения DSLs),
  • овеществление программы (обеспечение программ средствами для проверки их собственный код),
  • само-оптимизирование (само-применение домен-специфического оптимизации на основе овеществления программы),
  • алгоритмические программы построение (генерация кода, который утомительно писать с помощью абстракции, поддерживаемые языком программирования).

далее в меню, есть экспериментальные макро-функции, такие как макросы типа, квазиквоты, нетипизированные макросы и даже больше. Очевидно, что на это есть спрос!

все это кажется хорошими функциями для людей, которые строят очень сложные библиотеки с сильным пониманием Scala. Но предлагают ли макросы что-то и для среднего разработчика Scala? Будет ли использование макросов делать мой код Scala лучше?

1 ответов


как "средний" разработчик Scala, вы, скорее всего, не будете писать макросы самостоятельно, если у вас нет очень веской причины.

макросы-это метод метапрограммирования времени компиляции, то есть вы программируете программы. Например, def-макрос, который является частью Scala 2.10, хотя и все еще "экспериментальный", выглядит как обычный метод, но всякий раз, когда вы вызываете этот метод в своем коде, компилятор заменит этот вызов тем, что этот макрос, скрытый за этим методом, будет производить (новый фрагмент кода.)


очень простой пример. Включить дату, когда ваш проект был скомпилирован в код:

import java.util.Date
import reflect.macros.Context
import language.experimental.macros

object CompileTime {
  def apply(): Date = macro applyImpl

  def applyImpl(c: Context)(): c.Expr[Date] = {
    import c.universe._
    val now     = System.currentTimeMillis() // this is executed during compilation!
    val nowExpr = c.Expr[Long](Literal(Constant(now)))
    val code    = reify(new Date(nowExpr.splice))
    c.Expr(code.tree)
  }
}

используя этот макрос (следующий код должен быть скомпилирован отдельно из кода макроса выше):

object MacroTest extends App {
  println(s"This project was compiled on ${CompileTime()}")
}

(Если вы выполните это несколько раз, вы увидите, что время компиляции действительно постоянный)


короче говоря, макросы предлагают функциональность, которая была не доступный в любом предыдущая версия Scala. Вы можете делать с макросами то, что не можете сделать иначе (часто вы можете писать подобные вещи, используя отражение среды выполнения, но макросы проверяются во время компиляции).

как пользователь, вы будете все больше и больше подвергаться библиотекам, которые включают макросы, потому что они могут предоставлять мощные конструкции, которые полностью безопасны для типов. Например, автоматические сериализаторы для JSON из класса case могут быть реализованы с помощью макросов, поскольку макрос может проверять тип вашего класс case и построить правильную структуру программы (AST) для чтения и записи этого класса case, без опасности сбоя во время выполнения.

некоторые случайные ссылки