Uvod u Clojure

1. Uvod

Clojure je funkcionalni programski jezik koji se u potpunosti izvodi na Java virtualnom stroju, na sličan način kao Scala i Kotlin. Clojure se smatra Lispovim derivatom i bit će poznat svima koji imaju iskustva s drugim Lisp jezicima.

Ovaj tutorial daje uvod u jezik Clojure, uvod u početak rada s njim i neke od ključnih pojmova kako funkcionira.

2. Instaliranje Clojurea

Clojure je dostupan kao instalacijski program i praktične skripte za upotrebu na Linuxu i macOS-u. Nažalost, u ovoj fazi Windows nema takav instalacijski program.

Međutim, Linux skripte mogu raditi u nečemu kao što je Cygwin ili Windows Bash. Tu je i internetska usluga koja se može koristiti za testiranje jezika, a starije verzije imaju samostalnu verziju koja se može koristiti.

2.1. Samostalno preuzimanje

Samostalnu JAR datoteku možete preuzeti s Maven Central. Nažalost, verzije starije od 1.8.0 više ne rade na ovaj način zbog JAR datoteke koja je podijeljena na manje module.

Jednom kada se preuzme ova JAR datoteka, možemo je koristiti kao interaktivni REPL jednostavno tretirajući je kao izvršnu JAR:

$ java -jar clojure-1.8.0.jar Clojure 1.8.0 korisnik =>

2.2. Web sučelje za REPL

Web sučelje za Clojure REPL dostupno je na //repl.it/languages/clojure kako bismo mogli pokušati bez potrebe za preuzimanjem bilo čega. Trenutno ovo podržava samo Clojure 1.8.0, a ne i novija izdanja.

2.3. Instalacijski program na MacOS-u

Ako koristite macOS i imate instaliran Homebrew, tada se najnovije izdanje Clojure može lako instalirati:

$ brew instaliraj clojure

Ovo će podržati najnoviju verziju Clojure - 1.10.0 u vrijeme pisanja ovog članka. Jednom instaliran, REPL možemo učitati jednostavnim korištenjem klojure ili clj naredbe:

$ clj Clojure 1.10.0 korisnik =>

2.4. Instalacijski program na Linuxu

Dostupna nam je samoinstalirajuća skripta ljuske za instaliranje alata na Linux:

$ curl -O //download.clojure.org/install/linux-install-1.10.0.411.sh $ chmod + x linux-install-1.10.0.411.sh $ sudo ./linux-install-1.10.0.411.sh

Kao i kod instalacijskog programa macOS, oni će biti dostupni za najnovija izdanja Clojurea i mogu se izvršiti pomoću klojure ili clj naredbe.

3. Uvod u Clojure REPL

Sve gore navedene mogućnosti omogućuju nam pristup Clojure REPL-u. Ovo je izravni Clojure ekvivalent JShell alata za Javu 9 i novije verzije i omogućuje nam da unesemo Clojure kôd i odmah vidimo rezultat. Ovo je fantastičan način eksperimentiranja i otkrivanja kako funkcioniraju određene jezične značajke.

Nakon što se REPL učita, imat ćemo upit u kojem se može unijeti i odmah izvršiti bilo koji standardni Clojure kôd. To uključuje jednostavne Clojure konstrukcije, kao i interakciju s drugim Java knjižnicama - premda moraju biti dostupne na putu predavanja za učitavanje.

Upit REPL pokazatelj je trenutnog prostora imena u kojem radimo. Za većinu našeg rada ovo je korisnik prostor imena, i tako će upit biti:

korisnik =>

Sve u ostatku ovog članka pretpostavit će da imamo pristup Clojure REPL-u i svi će raditi izravno u bilo kojem takvom alatu.

4. Osnove jezika

Jezik Clojure izgleda vrlo različito od mnogih drugih jezika temeljenih na JVM-u i možda će se činiti vrlo neobičnim za početak. Smatra se dijalektom Lisp i ima vrlo sličnu sintaksu i funkcionalnost kao i drugi Lisp jezici.

Mnogo koda koji pišemo na Clojureu - kao i kod ostalih Lisp dijalekata - izražava se u obliku Popisa. Tada se popisi mogu procijeniti kako bi se dobili rezultati - bilo u obliku više popisa ili jednostavnih vrijednosti.

Na primjer:

(+ 1 2) ; = 3

Ovo je popis koji se sastoji od tri elementa. Simbol "+" označava da izvršavamo ovaj poziv - dodatak. Preostali elementi se zatim koriste s ovim pozivom. Dakle, ovo se ocjenjuje na "1 + 2".

Korištenjem ovdje sintakse Popisa, to se može trivijalno proširiti. Na primjer, možemo učiniti:

(+ 1 2 3 4 5) ; = 15

A ovo se ocjenjuje na "1 + 2 + 3 + 4 + 5".

Obratite pažnju i na znak dvotačke. Ovo se koristi u Clojureu za označavanje komentara i nije kraj izraza kao što bismo vidjeli na Javi.

4.1. Jednostavan Vrste

Clojure je izgrađen na vrhu JVM-a i kao takvi imamo pristup istim standardnim vrstama kao i bilo koji drugi Java program. Tipovi se obično zaključuju automatski i ne trebaju biti izričito navedeni.

Na primjer:

123; Dugački 1,23; Dvostruko "Zdravo"; Niz istinit; Booleova

Možemo odrediti i neke složenije vrste, koristeći posebne prefikse ili sufikse:

42N; clojure.lang.BigInt 3.14159M; java.math.BigDecimal 1/3; clojure.lang.Ratio # "[A-Za-z] +"; java.util.regex.Pattern

Imajte na umu da clojure.lang.BigInt vrsta se koristi umjesto java.math.BigInteger. To je zato što tip Clojure ima neke manje optimizacije i popravke.

4.2. Ključne riječi i simboli

Clojure nam daje koncept i ključnih riječi i simbola. Ključne riječi odnose se samo na sebe i često se koriste za stvari kao što su ključevi karte. Simboli su, s druge strane, nazivi koji se koriste za upućivanje na druge stvari. Na primjer, definicije varijabli i nazivi funkcija su simboli.

Ključne riječi možemo konstruirati pomoću imena s prefiksom dvotačke:

korisnik =>: kw: kw korisnik =>: a: a

Ključne riječi imaju izravnu ravnopravnost same sa sobom, a ne s ničim drugim:

user => (=: a: a) true user => (=: a: b) false user => (=: a "a") false

Većina drugih stvari u Clojureu koje nisu jednostavne vrijednosti smatraju se simbolima. Oni procjenjuju na sve na što se odnose, dok ključna riječ uvijek sama procjenjuje:

korisnik => (def a 1) # 'korisnik / korisnik =>: a: korisnik => a 1

4.3. Prostori imena

Jezik Clojure ima koncept prostora imena za organiziranje našeg koda. Svaki dio koda koji napišemo živi u prostoru imena.

Prema zadanim postavkama, REPL se izvodi u korisnik prostor imena - kao što se vidi u poruci koja navodi "korisnik =>".

Prostor imena možemo stvarati i mijenjati pomoću ns ključna riječ:

korisnik => (ns new.ns) nil new.ns =>

Nakon što promijenimo prostor imena, sve što je definirano u starom više nam nije dostupno, a sve što je definirano u novom sada je dostupno.

Definicijama možemo pristupiti kroz prostore imena potpunim kvalificiranjem. Na primjer, prostor imena clojure.niza definira funkciju velika slova.

Ako smo u clojure.niza prostoru imena, možemo mu pristupiti izravno. Ako nismo, onda to moramo kvalificirati kao clojure.niza / velika slova:

korisnik => (clojure.string / velika slova "zdravo") "POZDRAV" korisnik => (velika slova "zdravo"); To nije vidljivo u sintaksnoj pogrešci sintaksne pogreške "user" u (REPL: 1: 1). Nije moguće riješiti simbol: velika slova u ovom kontekstu user => (ns clojure.string) nil clojure.string => (velika slova "zdravo"); To je vidljivo jer smo sada u prostoru imena "clojure.string" "DOBRO POZDRAVE"

Također možemo koristiti zahtijevatiključna riječ za lakši pristup definicijama iz drugog prostora imena. Dva su glavna načina na koja to možemo koristiti - definirati prostor imena s kraćim imenom kako bi ga bilo lakše koristiti i pristupiti definicijama iz drugog prostora imena bez izravnog prefiksa:

clojure.string => (zahtijeva '[clojure.string: kao str]) nil clojure.string => (str / velika slova "Zdravo") "POZDRAV" korisnik => (zahtijeva' [clojure.string: kao str: uputite [velika slova]]) nil user => (velika slova "Hello") "HELLO"

Oboje utječu samo na trenutni prostor imena, pa će promjena u drugi morati imati novi zahtijeva. To pomaže da naši imenski prostori budu čistiji i omoguće nam pristup samo onome što nam treba.

4.4. Varijable

Jednom kada znamo definirati jednostavne vrijednosti, možemo ih dodijeliti varijablama. To možemo učiniti pomoću ključne riječi def:

korisnik => (def a 123) # 'korisnik / a

Nakon što to učinimo, možemo upotrijebiti simbol abilo gdje želimo predstaviti ovu vrijednost:

korisnik => a 123

Definicije varijabli mogu biti jednostavne ili komplicirane koliko god želimo.

Na primjer, da definiramo varijablu kao zbroj brojeva, možemo učiniti:

korisnik => (def b (+ 1 2 3 4 5)) # 'korisnik / b korisnik => b 15

Primijetite da nikad ne moramo deklarirati varijablu ili naznačiti koji je tip. Clojure nam sve ovo automatski određuje.

Ako pokušamo koristiti varijablu koja nije definirana, tada ćemo umjesto toga dobiti pogrešku:

korisnik => nepoznata sintaksna pogreška pri sastavljanju u (REPL: 0: 0). Nije moguće riješiti simbol: nepoznat u ovom kontekstu korisnik => (def c (+ 1 nepoznat)) Pogreška u sintaksi sastavljanja u (REPL: 1: 8). Nije moguće riješiti simbol: nepoznat u ovom kontekstu

Primijetite da je izlaz def funkcija izgleda malo drugačije od ulazne. Definiranje varijable a vraća niz od ‘Korisnik / a. To je zato što je rezultat simbol, a ovaj simbol je definiran u trenutnom prostoru imena.

4.5. Funkcije

Već smo vidjeli nekoliko primjera kako pozivati ​​funkcije u Clojureu. Izrađujemo popis koji započinje s funkcijom koju treba pozvati, a zatim svim parametrima.

Kada ovaj popis procijeni, dobivamo povratnu vrijednost iz funkcije. Na primjer:

user => (java.time.Instant / now) #object [java.time.Instant 0x4b6690c0 "2019-01-15T07: 54: 01.516Z"] user => (java.time.Instant / parse "2019-01- 15T07: 55: 00Z ") #object [java.time.Instant 0x6b8d96d9" 2019-01-15T07: 55: 00Z "] user => (java.time.OffsetDateTime / of 2019 01 15 7 56 0 0 java.time. ZoneOffset / UTC) #object [java.time.OffsetDateTime 0xf80945f "2019-01-15T07: 56Z"]

Također možemo ugnijezditi pozive funkcijama, jer kada želimo proslijediti izlaz jednog poziva funkcije kao parametar drugom:

user => (java.time.OffsetDateTime / of 2018 01 15 7 57 0 0 (java.time.ZoneOffset / ofHours -5)) #object [java.time.OffsetDateTime 0x1cdc4c27 "2018-01-15T07: 57-05: 00 "]

Također, možemo definirati i svoje funkcije ako želimo. Funkcije se kreiraju pomoću fn naredba:

korisnik => (fn [a b] (println "Dodavanje brojeva" a "i" b) (+ a b)) #object [korisnik $ eval165 $ fn__166 0x5644dc81 "[e-pošta zaštićena]"]

Nažalost, ovo ne daje funkciji ime koje se može koristiti. Umjesto toga, možemo definirati simbol koji predstavlja ovu funkciju pomoću def, točno onako kako smo vidjeli za varijable:

korisnik => (def dodaj (fn [a b] (println "Dodavanje brojeva" a "i" b) (+ a b))) # 'korisnik / dodaj

Sad kad smo definirali ovu funkciju, možemo je nazvati jednako kao i bilo koju drugu funkciju:

korisnik => (dodaj 1 2) Dodavanje brojeva 1 i 2 3

Kao praktičnost, Clojure nam također omogućuje upotrebu defn za definiranje funkcije s imenom u jednom potezu.

Na primjer:

korisnik => (defn pod [a b] (println "Oduzimanje" b "od" a) (- a b)) # 'korisnik / podkorisnik => (pod 5 2) Oduzimanje 2 od 5 3

4.6. Let i lokalne varijable

The def poziv definira simbol koji je globalni za trenutni prostor imena. To obično nije ono što se želi prilikom izvršavanja koda. Umjesto toga, Clojure nudi neka poziv za definiranje lokalnih varijabli u bloku. To je posebno korisno kada ih koristite unutar funkcija, gdje ne želite da varijable propuštaju izvan funkcije.

Na primjer, mogli bismo definirati našu podfunkciju:

korisnik => (defn pod [a b] (def rezultat (- a b)) (println "Rezultat:" rezultat) rezultat) # 'korisnik / pod

Međutim, upotreba ovoga ima sljedeću neočekivanu nuspojavu:

korisnik => (pod 1 2) Rezultat: -1 -1 korisnik => rezultat; I dalje vidljiv izvan funkcije -1

Umjesto toga, prepišimo ga pomoću neka:

korisnik => (defn pod [ab] (neka [rezultat (- ab)] (println "Rezultat:" rezultat) rezultat)) # 'korisnik / podkorisnik => (pod 1 2) Rezultat: -1 -1 korisnik = > rezultat Sastavljanje pogreške u sintaksi na (REPL: 0: 0). Nije moguće riješiti simbol: rezultat u ovom kontekstu

Ovaj put proizlaziti simbol nije vidljiv izvan funkcije. Ili, doista, izvan neka blok u kojem je korišten.

5. Zbirke

Do sada smo uglavnom komunicirali s jednostavnim vrijednostima. Vidjeli smo i popise, ali ništa više. Clojure ima čitav niz zbirki koje se mogu koristiti, ali se sastoje od popisa, vektora, karata i skupova:

  • Vektor je poredani popis vrijednosti - bilo koja proizvoljna vrijednost može se staviti u vektor, uključujući ostale zbirke.
  • Skup je neuređena zbirka vrijednosti i nikada ne može sadržavati istu vrijednost više puta.
  • Karta je jednostavan skup parova ključ / vrijednost. Vrlo je često koristiti ključne riječi kao ključeve na karti, ali možemo koristiti bilo koju vrijednost koja nam se sviđa, uključujući ostale zbirke.
  • Popis je vrlo sličan vektoru. Razlika je slična onoj između ArrayList i a LinkedList na Javi. Tipično se daje prednost vektoru, ali popis je bolji ako želimo dodavati elemente na početak ili ako elementima želimo pristupiti samo u slijedu.

5.1. Izrada zbirki

Stvaranje svake od njih može se izvršiti pomoću stenografskog zapisa ili pomoću poziva funkcije:

; Korisnik vektora => [1 2 3] [1 2 3] korisnik => (vektor 1 2 3) [1 2 3]; Popis korisnika => '(1 2 3) (1 2 3) korisnik => (popis 1 2 3) (1 2 3); Postavi korisnika => # {1 2 3} # {1 3 2} user => (hash-set 1 2 3) # {1 3 2}; Korisnik karte => {: a 1: b 2} {: a 1,: b 2} user => (hash-map: a 1: b 2) {: b 2,: a 1}

Primijetite da Postavi i Karta primjeri ne vraćaju vrijednosti istim redoslijedom. To je zato što su ove zbirke same po sebi neuređene, a ono što vidimo ovisi o tome kako su predstavljene u sjećanju.

Također možemo vidjeti da je sintaksa za stvaranje popisa vrlo slična standardnoj Clojure sintaksi za izraze. Izraz Clojure zapravo je popis koji se ocjenjuje, dok znak apostrofa ovdje pokazuje da želimo stvarni popis vrijednosti umjesto da ga procjenjujemo.

Možemo, naravno, varijabli dodijeliti zbirku na isti način kao i bilo kojoj drugoj vrijednosti. Također možemo koristiti jednu zbirku kao ključ ili vrijednost unutar druge zbirke.

Popisi se smatraju a dalje. To znači da klasa implementira ISeq sučelje. Sve ostale zbirke mogu se pretvoriti u dalje koristiti dalje funkcija:

korisnik => (seq [1 2 3]) (1 2 3) user => (seq # {1 2 3}) (1 3 2) user => (seq {: a 1 2 3}) ([: a 1] [2 3])

5.2. Pristup zbirkama

Jednom kad imamo zbirku, možemo s njom komunicirati kako bi se vrijednosti vratile natrag. Kako to možemo učiniti, malo ovisi o dotičnoj zbirci, jer svaka od njih ima različitu semantiku.

Vektori su jedina zbirka koja nam omogućuje dobivanje bilo koje proizvoljne vrijednosti indeksom. To se postiže procjenom vektora i indeksa kao izraza:

korisnik => (moj vektor 2); [1 2 3] 3

To isto, koristeći istu sintaksu, možemo učiniti i za karte:

korisnik => (moja mapa: b) 2

Također imamo funkcije za pristup vektorima i popisima kako bismo dobili prvu vrijednost, zadnju vrijednost i ostatak popisa:

korisnik => (prvi moj vektor) 1 korisnik => (zadnji moj popis) 3 korisnik => (sljedeći moj vektor) (2 3)

Karte imaju dodatne funkcije za dobivanje cijelog popisa ključeva i vrijednosti:

korisnik => (tipke my-map) (: a: b) user => (vals my-map) (1 2)

Jedini stvarni pristup koji moramo postaviti je provjeriti je li određeni element član.

Ovo izgleda vrlo slično pristupu bilo kojoj drugoj zbirci:

korisnik => (moj set 1) 1 korisnik => (moj set 5) ništa

5.3. Identificiranje kolekcija

Vidjeli smo da način na koji pristupamo zbirci varira ovisno o vrsti zbirke koju imamo. Imamo skup funkcija pomoću kojih to možemo odrediti, kako na specifičan, tako i na općenitiji način.

Svaka naša zbirka ima određenu funkciju utvrđivanja je li zadana vrijednost tog tipa - popis? za popise, postaviti? za setove i tako dalje. Uz to postoji seq? za utvrđivanje je li zadana vrijednost a dalje bilo koje vrste, i asocijativni? kako bi se utvrdilo dopušta li zadana vrijednost asocijativni pristup bilo koje vrste - što znači vektori i karte:

korisnik => (vektor? [1 2 3]); Vektor je vektor pravi korisnik => (vektor? # {1 2 3}); Skup nije vektor lažni korisnik => (popis? '(1 2 3)); Popis je popis pravi korisnik => (popis? [1 2 3]); Vektor nije popis lažni korisnik => (karta? {: A 1: b 2}); Karta je pravi korisnik karte => (karta? # {1 2 3}); Skup nije karta lažni korisnik => (seq? '(1 2 3)); Popis je seq pravi korisnik => (seq? [1 2 3]); Vektor nije seq lažni korisnik => (seq? (Seq [1 2 3])); Vektor se može pretvoriti u seq true user => (asocijativni? {: A 1: b 2}); Karta je asocijativni pravi korisnik => (asocijativni? [1 2 3]); Vektor je asocijativni pravi korisnik => (asocijativni? '(1 2 3)); Popis nije asocijativno lažan

5.4. Mutiranje zbirki

U Clojureu, kao i u većini funkcionalnih jezika, sve su zbirke nepromjenjive. Sve što učinimo kako bismo promijenili kolekciju rezultira potpuno novom kolekcijom koja je stvorena da predstavlja promjene. To može donijeti velike koristi u pogledu učinkovitosti i znači da ne postoji rizik od slučajnih nuspojava.

Međutim, također moramo biti oprezni da to razumijemo, inače se neće dogoditi očekivane promjene u našim kolekcijama.

Dodavanje novih elemenata u vektor, popis ili skup vrši se pomoću konj. To u svakom od ovih slučajeva djeluje različito, ali s istom osnovnom namjerom:

korisnik => (conj [1 2 3] 4); Dodaje na kraj [1 2 3 4] korisnik => (conj '(1 2 3) 4); Dodaje na početak (4 1 2 3) user => (conj # {1 2 3} 4); Neuređeni # {1 4 3 2} korisnik => (conj # {1 2 3} 3); Dodavanje već prisutnog unosa ne znači ništa # {1 3 2}

Također možemo ukloniti unose iz skupa pomoću disj. Imajte na umu da ovo ne radi na popisu ili vektoru jer su strogo poredani:

korisnik => (disj # {1 2 3} 2); Uklanja unos # {1 3} user => (disj # {1 2 3} 4); Ne radi ništa jer unos nije bio prisutan # {1 3 2}

Dodavanje novih elemenata na kartu vrši se pomoću izv. prof. Također možemo ukloniti unose s karte pomoću dissoc:

korisnik => (izv. {: a 1: b 2}: c 3); Dodaje novi ključ {: a 1,: b 2,: c 3} korisnik => (izv. {: A 1: b 2}: b 3); Ažurira postojeći ključ {: a 1,: b 3} user => (dissoc {: a 1: b 2}: b); Uklanja postojeći ključ {: a 1} user => (dissoc {: a 1: b 2}: c); Ne radi ništa jer ključ nije bio prisutan {: a 1,: b 2}

5.5. Konstrukcije funkcionalnog programiranja

Clojure je u svojoj osnovi funkcionalan programski jezik. Ovo znači to imamo pristup mnogim tradicionalnim konceptima funkcionalnog programiranja - kao što su karta, filtar, i smanjiti. Oni uglavnom rade isto kao i u drugim jezicima. Točna sintaksa ipak se može malo razlikovati.

Konkretno, ove funkcije obično uzimaju funkciju za primjenu kao prvi argument, a kolekciju za primjenu kao drugi argument:

korisnik => (karta uklj. [1 2 3]); Povećajte svaku vrijednost u vektoru (2 3 4) user => (map inc # {1 2 3}); Povećati svaku vrijednost u skupu (2 4 3) user => (filtrirati neparno? [1 2 3 4 5]); Vrati samo neparne vrijednosti (1 3 5) user => (ukloniti neparne? [1 2 3 4 5]); Vrati samo neparne vrijednosti (2 4) user => (smanji + [1 2 3 4 5]); Zbrojite sve vrijednosti, vraćajući zbroj 15

6. Kontrolne strukture

Kao i kod svih jezika opće namjene, Clojure također nudi standardne upravljačke strukture, poput uvjetnih uvjeta i petlji.

6.1. Kondicionali

Uvjetnicima se bavi ako izjava. Za to su potrebna tri parametra: test, blok koji treba izvršiti ako je test pravii blok za izvršavanje ako je test lažno. Svaka od njih može biti jednostavna vrijednost ili standardni popis koji će se procijeniti na zahtjev:

korisnik => (ako je tačno 1 2) 1 korisnik => (ako je tačno 1 2) 2

Naš test može biti sve što nam treba - ne mora biti točno netočno vrijednost. To također može biti blok koji se procjenjuje kako bi nam dao vrijednost koja nam je potrebna:

korisnik => (if (> 1 2) "True" "False") "False"

Sve standardne provjere, uključujući =, >, i <, ovdje se može koristiti. Tu je i skup predikata koji se mogu koristiti iz raznih drugih razloga - neke smo vidjeli već prilikom gledanja zbirki, na primjer:

korisnik => (ako (nepar? 1) "1 je neparan" "1 je paran") "1 je neparan"

Test uopće može vratiti bilo koju vrijednost - ne treba samo biti pravi ili lažno. Međutim, smatra se da jest pravi ako je vrijednost išta osim lažno ili nula. To se razlikuje od načina na koji funkcionira JavaScript, gdje postoji velik skup vrijednosti koje se smatraju "istinitima", ali ne i pravi:

user => (ako je 0 "True" "False") "True" user => (if [] "True" "False") "True" user => (if nil "True" "False") "False"

6.2. Looping

Naša funkcionalna podrška za kolekcije obrađuje velik dio petlje - umjesto pisanja petlje preko zbirke, koristimo standardne funkcije i prepuštamo jeziku da iteraciju radi umjesto nas.

Izvan toga, petlja se u potpunosti koristi rekurzijom. Možemo pisati rekurzivne funkcije ili možemo koristiti petlja i ponoviti ključne riječi za pisanje rekurzivne petlje stila:

korisnik => (petlja [akum [] i 0] (ako (= i 10) akumulacija (ponavljanje (konj akumulacija) (uklj. i)))) [0 1 2 3 4 5 6 7 8 9]

The petlja poziv započinje unutarnji blok koji se izvršava na svakoj iteraciji i započinje postavljanjem nekih početnih parametara. The ponoviti call zatim poziva natrag u petlju, pružajući sljedeće parametre koji će se koristiti za iteraciju. Ako ponoviti se ne poziva, tada se petlja završava.

U ovom slučaju, petlju vršimo svaki put kad ja vrijednost nije jednaka 10, a onda čim je jednaka 10, umjesto toga vraćamo akumulirani vektor brojeva.

7. Sažetak

Ovaj je članak dao uvod u programski jezik Clojure i prikazuje kako funkcionira sintaksa i neke stvari koje s njom možete učiniti. Ovo je samo uvodna razina i ne ulazi u dubine svega što se s jezikom može učiniti.

Međutim, zašto ga ne biste podigli, pokušali i vidjeli što možete učiniti s njim.