0Pricing
Scala for Backend Engineering & Functional Programming · レッスン

マクロの基礎

コンパイル時のコードです。

「マクロの基礎」はCoddyKit上の無料Scala for Backend Engineering & Functional Programmingレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはScala for Backend Engineering & Functional Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。

マクロとは

マクロとは、コンパイル時に実行され、別のコードを生成するコードです。Scala 3 のマクロでは、引数を調べたり、式を構築したりして、プログラムのコンパイル前にその式をプログラムへ出力できます。

Inline + Macro パターン

マクロは、${ ... } が付いたメソッドへ処理を委譲する inline def から呼び出します。inline def が公開 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)
}

マクロの配置場所

マクロ実装は、それを使用するコードより前にコンパイルする必要があります。通常は別のファイルまたはモジュールに配置します。コンパイラーは呼び出し側のコンパイル中にマクロを実行します。

一般的なユースケース

マクロは次の用途で活用されます:

  • 型クラスの導出(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 による抽出
  • エラー報告と衛生性

次はクォートとスプライスです。

よくある質問

「マクロの基礎」レッスンは無料ですか?

はい。「マクロの基礎」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Scala for Backend Engineering & Functional Programmingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。

「マクロの基礎」で何を学びますか?

コンパイル時のコードです。 ブラウザで直接実行するハンズオンコードでScala for Backend Engineering & Functional Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Scala for Backend Engineering & Functional Programmingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのScala for Backend Engineering & Functional Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「マクロの基礎」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このScala for Backend Engineering & Functional Programmingレッスンでコードを書いて実行できますか?

はい。すべてのScala for Backend Engineering & Functional Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. インラインメソッド
  2. マクロの基礎
  3. Quotes と Splices
  4. 実践的なマクロ
← Scala for Backend Engineering & Functional Programmingに戻る