Funktionel programmering i Clojure og backendudvikling på JVM · Lektion

Forståelse af Clojure-makroer

Udforsk begrebet makroer, hvordan de adskiller sig fra funktioner, og hvordan de kan udvide Clojures syntaks.

Lektion 1 af 411 trin

Forståelse af Clojure-makroer er en gratis Funktionel programmering i Clojure og backendudvikling på JVM-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Funktionel programmering i Clojure og backendudvikling på JVM, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Funktionel programmering i Clojure og backendudvikling på JVM-kurset indeholder 4 lektioner i alt.

Clojure-makroer: Kode, der skriver kode

Velkommen til Clojure-makroernes verden! Makroer er en kraftfuld funktion, der lader dig udvide Clojures syntaks.

Tænk på dem som kode, der arbejder på anden kode, før den køres. De lader dig oprette nye sprogkonstruktioner, der er tilpasset dine behov.

Makroer sammenlignet med funktioner: Vigtige forskelle

Det er vigtigt at forstå, hvordan makroer adskiller sig fra almindelige funktioner:

  • Funktioner: Udføres ved kørselstid. De tager data som argumenter og returnerer data.
  • Makroer: Udføres ved kompileringstid. De tager kode (eller former) som argumenter og returnerer kode.

Makroer transformerer din kode, før programmet overhovedet begynder at køre!

Clojures kode som data (homoikonisk)

Clojure er homoikonisk, hvilket betyder, at koden repræsenteres som standarddatastrukturer. Det er afgørende for makroer!

  • Kode skrives som lister, vektorer og symboler.
  • Makroer modtager disse datastrukturer som input.
  • De manipulerer disse datastrukturer for at producere ny kode.

Denne tilgang med »kode som data« gør makroer utroligt fleksible.

Citering: Forhindring af evaluering

For at arbejde med kode som data skal vi forhindre, at den evalueres med det samme. Det er her, citering kommer ind i billedet.

Du kan bruge (quote ...) eller den korte form ' til at fortælle Clojure: »Behandl dette som data, ikke som kode, der skal udføres.«

Prøv at køre dette eksempel:

(defn -main []
  (println (quote (+ 1 2)))
  (println '(+ 1 2))
  (println (type '(+ 1 2))))

Afcitering: Indsættelse af værdier i kode

Når du opbygger ny kode med makroer, har du ofte brug for at indsætte faktiske værdier eller evaluerede udtryk i den citerede kode.

Det gør du med afcitering ved hjælp af (unquote ...) eller den korte form ~. Det fortæller Clojure: »Evaluer denne del, selvom den er inde i citeret kode.«

Backtick-tegnet ` er syntax-quote, som automatisk citerer alt, medmindre det afciteres. Det bruges ofte til makroer.

Se det i praksis:

(defn -main []
  (let [x 10]
    (println `(do-something ~x (+ ~x 5))))
  (let [name "Alice"]
    (println `(greet ~name))))

Splice-afcitering: Indsættelse af sekvenser

Hvad nu, hvis du har en sekvens af elementer og vil indsætte dem som individuelle elementer i en citeret liste?

Det er her, splice-afcitering ((unquote-splicing ...) eller ~@) virkelig er nyttig. Den »fletter« elementerne fra en sekvens direkte ind i den omgivende liste.

Det er særligt nyttigt til makroer, der tager et variabelt antal argumenter.

(defn -main []
  (let [args '(a b c)]
    (println `(my-function 1 2 ~@args 3))))

Oprettelse af en simpel makro: `my-when`

Lad os oprette en makro, der minder om Clojures when. Vores my-when-makro udfører en kodeblok, men kun hvis et testudtryk er sandt.

Bemærk, hvordan vi bruger ` til den overordnede struktur, ~ til testen og ~@ til blokudtrykkene.

(defmacro my-when [test & body]
  `(if ~test
     (do ~@body)))

(defn -main []
  (my-when true
    (println "It's true!")
    (println "Multiple forms run."))

  (my-when false
    (println "This won't run.")))

Undersøgelse af makroudvidelse

For at forstå, hvad din makro gør, kan du undersøge dens udvidelse.

  • macroexpand-1: Udvider det yderste makrokald én gang.
  • macroexpand: Udvider alle indlejrede makrokald, indtil der ikke kan udvides flere makroer.

Disse funktioner er uvurderlige ved fejlfinding af makroer!

(defmacro my-when [test & body]
  `(if ~test
     (do ~@body)))

(defn -main []
  (println "\nMacroexpand-1:")
  (println (macroexpand-1 '(my-when true (println "Hello"))))

  (println "\nMacroexpand (full expansion):")
  (println (macroexpand '(my-when true (println "Hello")))))

Makrohygiejne og gensymer

Et almindeligt problem med makroer er navneindfangning. Det sker, når et symbol i makroens udvidelse ved et uheld kommer i konflikt med et symbol i den kode, hvor makroen bruges.

For at forhindre dette kan du bruge gensymer (genererede symboler), som garanteres at være unikke. I syntax-quote kan du sætte # efter et symbol for at gøre det til et gensym, f.eks. `foo#.

Det sikrer, at makroens interne variabler ikke kolliderer med brugerdefinerede variabler.

Tjek din viden om makroer

Lad os tjekke din forståelse af Clojure-makroer og deres centrale begreber.

Opsummering: Sådan mestrer du Clojure-makroer

Du har nu udforsket Clojure-makroernes kraftfulde verden!

  • Makroer er konstruktioner ved kompileringstid, der transformer kode.
  • De udnytter Clojures homoikonicitet (kode som data).
  • Vigtige værktøjer omfatter quote ('), unquote (~) og splice unquote (~@) til at manipulere kodeformer.
  • syntax-quote (`) er en praktisk måde at skrive makroer på.
  • Værktøjer som macroexpand og gensymer hjælper med at skrive og fejlfinde robuste makroer.

Makroer er avancerede, men uvurderlige til at skabe meget udtryksfulde og domænespecifikke sprog i Clojure. Bliv ved med at eksperimentere!

Gratis at komme i gang

Lær Clojure med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
12
Lektioner
48

Ofte stillede spørgsmål

Er lektionen “Forståelse af Clojure-makroer” gratis?

Ja — hele teksten til “Forståelse af Clojure-makroer” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Funktionel programmering i Clojure og backendudvikling på JVM-kurset, skal du opgradere til CoddyKit PRO. Funktionel programmering i Clojure og backendudvikling på JVM-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Forståelse af Clojure-makroer”?

Udforsk begrebet makroer, hvordan de adskiller sig fra funktioner, og hvordan de kan udvide Clojures syntaks. Du øver dig i Funktionel programmering i Clojure og backendudvikling på JVM med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Funktionel programmering i Clojure og backendudvikling på JVM?

Der kræves ingen tidligere erfaring. Funktionel programmering i Clojure og backendudvikling på JVM på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.

Hvor lang tid tager lektionen “Forståelse af Clojure-makroer”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Funktionel programmering i Clojure og backendudvikling på JVM-lektion?

Ja. Alle Funktionel programmering i Clojure og backendudvikling på JVM-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Forståelse af Clojure-makroer
  2. Definition og brug af namespaces
  3. Organisering af kode med moduler
  4. Protokoller og multimethods til polymorfi
← Tilbage til Funktionel programmering i Clojure og backendudvikling på JVM