0Pricing
Scala for Backend Engineering & Functional Programming · Урок

Основы макросов

Код на этапе компиляции

«Основы макросов» — бесплатный урок Scala for Backend Engineering & Functional Programming на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Scala for Backend Engineering & Functional Programming, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.

Что такое макрос?

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

Шаблон Inline + Macro

Макрос вызывается из inline def, который делегирует выполнение методу, отмеченному с помощью ${ ... }. Inline-определение является общедоступным API, а реализация макроса выполняется в компиляторе.

import scala.quoted.*

inline def power(x: Double, inline n: Int): Double =
  ${ powerImpl('x, 'n) }

Контекст Quotes

Каждая реализация макроса принимает неявный контекст Quotes. Он предоставляет доступ к API отражения, а также возможность создавать выражения и вставлять их в код.

import scala.quoted.*

def powerImpl(x: Expr[Double], n: Expr[Int])(using Quotes): Expr[Double] =
  ???

Expr[T]

Expr[T] представляет типизированное выражение типа T как данные времени компиляции. Макросы получают и возвращают значения Expr.

Подъём значений в Expr

Expr(value) поднимает вычисленное макросом значение времени выполнения в выражение, чтобы затем вставить его обратно. Это работает для любого типа, у которого есть экземпляр ToExpr.

import scala.quoted.*

def constImpl(using Quotes): Expr[Int] = Expr(42)

Извлечение константных аргументов

n.value (или n.valueOrAbort) извлекает константу из Expr, если аргумент известен статически, чтобы макрос мог использовать её в ветвлении.

import scala.quoted.*

def powerImpl(x: Expr[Double], n: Expr[Int])(using Quotes): Expr[Double] = {
  val exp = n.valueOrAbort
  ??? // build x*x*...*x exp times
}

Сообщение об ошибках

Используйте quotes.reflect.report.errorAndAbort, чтобы выдать ошибку компиляции с сообщением и указанием местоположения, если предварительные условия макроса не выполнены.

import scala.quoted.*

def check(n: Expr[Int])(using q: Quotes): Expr[Int] = {
  import q.reflect.*
  val v = n.valueOrAbort
  if (v < 0) report.errorAndAbort("must be >= 0")
  Expr(v)
}

Где находятся макросы

Реализации макросов должны быть скомпилированы до кода, который их использует, — обычно в отдельном файле или модуле. Компилятор выполняет их во время компиляции вызывающего кода.

Распространённые случаи использования

Макросы используются для:

  • выведения экземпляров typeclass (кодеки JSON и т. д.)
  • проверки во время компиляции (регулярные выражения, SQL)
  • ведения журнала с фиксацией позиций в исходном коде
  • абстракций без затрат во время выполнения

Безопасность и гигиена

Макросы Scala 3 являются гигиеничными: сгенерированные идентификаторы не могут случайно захватить пользовательские переменные, а система типов проверяет сгенерированный код, предотвращая многие классические ошибки макросов.

Эквивалент во время выполнения

Макрос, вычисляющий степень во время компиляции, даёт тот же результат, что и эта самодостаточная версия, выполняемая во время работы программы, — но компилятор заранее встраивает умножения.

object Main {
  def power(x: Double, n: Int): Double =
    if (n == 0) 1.0 else x * power(x, n - 1)
  def main(args: Array[String]): Unit = {
    println(power(2.0, 3)) // 8.0
  }
}

Быстрая проверка

Какой тип представляет типизированное выражение времени компиляции, которое получают и возвращают макросы?

Итоги

Вы изучили основы макросов:

  • макросы выполняются во время компиляции с помощью шаблона inline def ... ${ }
  • контекст Quotes и Expr[T]
  • подъём с помощью Expr(...) и извлечение с помощью .value
  • сообщение об ошибках и гигиена

Далее: quotes и вставки.

Часто задаваемые вопросы

Урок «Основы макросов» бесплатный?

Да — полный текст урока «Основы макросов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Scala for Backend Engineering & Functional Programming, подпишись на CoddyKit PRO. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.

Чему я научусь в уроке «Основы макросов»?

Код на этапе компиляции Ты практикуешь Scala for Backend Engineering & Functional Programming с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Scala for Backend Engineering & Functional Programming?

Предыдущий опыт не требуется. Scala for Backend Engineering & Functional Programming на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Основы макросов»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Scala for Backend Engineering & Functional Programming?

Да. Каждый урок Scala for Backend Engineering & Functional Programming включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Встраиваемые методы
  2. Основы макросов
  3. Цитаты и вставки
  4. Практические макросы
← Назад к Scala for Backend Engineering & Functional Programming