Scala for Backend Engineering & Functional Programming · Lekcja

Quotes i splices

Kod jako dane

Lekcja 3 z 413 kroki

Quotes i splices to bezpłatna lekcja Scala for Backend Engineering & Functional Programming na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Scala for Backend Engineering & Functional Programming, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Scala for Backend Engineering & Functional Programming zawiera 4 lekcji w sumie.

Kod jako dane

Metaprogramowanie w Scali 3 traktuje kod jako dane. Quote przechwytuje fragment kodu jako Expr, a splice wstawia Expr z powrotem do kodu.

Quote: '{ ... }'

'{ expr } zamienia wyrażenie na Expr[T]. Kod nie jest wykonywany — staje się wartością, którą makro może modyfikować.

import scala.quoted.*

def greeting(using Quotes): Expr[String] = '{ "Hello, " + "world" }

Splice: ${ ... }

${ expr } wstawia Expr do otaczającego quote, łącząc wygenerowane fragmenty. Quote i splice są operacjami odwrotnymi.

import scala.quoted.*

def doubled(x: Expr[Int])(using Quotes): Expr[Int] = '{ ${ x } * 2 }

Wstawianie wartości podniesionych do poziomu kodu

Wewnątrz quote można wstawić wartość podniesioną za pomocą Expr(...), aby osadzić stałą znaną w czasie kompilacji w generowanym kodzie.

import scala.quoted.*

def addN(x: Expr[Int], n: Int)(using Quotes): Expr[Int] =
  '{ ${ x } + ${ Expr(n) } }

Rekurencyjne budowanie kodu

Makra budują złożone wyrażenia, łącząc quote i splice w pętlach lub rekurencji — na przykład rozwijając potęgowanie do wielokrotnego mnożenia.

import scala.quoted.*

def pow(x: Expr[Double], n: Int)(using Quotes): Expr[Double] =
  if (n == 0) '{ 1.0 } else '{ ${ x } * ${ pow(x, n - 1) } }

Dopasowywanie wzorców do quote

Można destrukturyzować kod, dopasowując go do wzorców quote. Pozwala to sprawdzić strukturę wyrażenia w celu jego optymalizacji lub przepisania.

import scala.quoted.*

def optimize(e: Expr[Int])(using Quotes): Expr[Int] = e match {
  case '{ ($a: Int) + 0 } => a
  case _                  => e
}

Type[T] i typy cytowane

Tak jak Expr[T] przechowuje wyrażenie, Type[T] przechowuje typ. Użyj '[T], aby zacytować typ, oraz given Type[T], aby wstawić go tam, gdzie wymagany jest typ.

import scala.quoted.*

def typeName[T](using t: Type[T], q: Quotes): Expr[String] =
  Expr(Type.show[T])

API reflect

W przypadku pracy na niższym poziomie quotes.reflect udostępnia abstrakcyjne drzewo składniowe (Term, Symbol, TypeRepr), dzięki czemu można sprawdzać lub budować kod wykraczający poza możliwości bezpośrednio oferowane przez quote.

import scala.quoted.*

def show(e: Expr[Any])(using q: Quotes): Expr[String] = {
  import q.reflect.*
  Expr(e.asTerm.show)
}

Przejście między poziomami

Konwertuj Expr na Term za pomocą asTerm, a następnie z powrotem za pomocą asExpr / asExprOf[T]. Łączy to wysokopoziomowe API quote z API refleksji.

import scala.quoted.*

def ident[T: Type](e: Expr[T])(using q: Quotes): Expr[T] = {
  import q.reflect.*
  e.asTerm.asExprOf[T]
}

Analogia czasu wykonywania

Przedstawione wcześniej rekurencyjne makro potęgowania rozwija się do zwykłych mnożeń. Ta samodzielna wersja wykonywana w czasie działania pokazuje ten sam wynik, który zwróciłby wygenerowany kod.

object Main {
  def pow(x: Double, n: Int): Double =
    if (n == 0) 1.0 else x * pow(x, n - 1)
  def main(args: Array[String]): Unit = {
    println(pow(3.0, 2)) // 9.0
  }
}

Quote i splice są operacjami odwrotnymi

Zapamiętaj tę dwoistość: '{ } podnosi kod do postaci Expr, a ${ } wstawia Expr z powrotem do kodu. Prawidłowe zagnieżdżanie tych konstrukcji jest podstawą budowania makr.

Szybkie sprawdzenie

Co operator splice ${ x } robi wewnątrz quote?

Podsumowanie

Utworzył(a) Pan(i) quote i splice:

  • '{ } cytuje kod jako Expr[T]
  • ${ } wstawia Expr do kodu
  • dopasowywanie wzorców quote do destrukturyzacji kodu
  • Type[T] i API reflect

Następnie: praktyczne makra.

Bezpłatny start

Ucz się Scala dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
39
Lekcje
143

Często zadawane pytania

Czy lekcja „Quotes i splices” jest bezpłatna?

Tak — pełny tekst „Quotes i splices” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Scala for Backend Engineering & Functional Programming, przejdź na CoddyKit PRO. Kurs Scala for Backend Engineering & Functional Programming zawiera 4 lekcji w sumie.

Co nauczysz się w „Quotes i splices”?

Kod jako dane Ćwiczysz Scala for Backend Engineering & Functional Programming z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Scala for Backend Engineering & Functional Programming?

Nie wymagamy żadnego doświadczenia. Scala for Backend Engineering & Functional Programming w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Quotes i splices”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Scala for Backend Engineering & Functional Programming?

Tak. Każda lekcja Scala for Backend Engineering & Functional Programming zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Metody inline
  2. Podstawy makr
  3. Quotes i splices
  4. Praktyczne makra
← Powrót do Scala for Backend Engineering & Functional Programming