Programowanie w jezyku Clojure 2

background image
background image

Tytuł oryginału: Programming Clojure

Tłumaczenie: Tomasz Walczak

ISBN: 978-83-246-5372-0

© Helion 2013.
All rights reserved.

Copyright © 2012 The Pragmatic Programmers, LLC.
All rights reserved.

No part of this publication may be reproduced, stored in retrieval system, or transmitted,
in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise,
without the prior consent of the poublisher.

Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej
publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną,
fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym
powoduje naruszenie praw autorskich niniejszej publikacji.

Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi
ich właścicieli.

Wydawnictwo HELION dołożyło wszelkich starań, by zawarte w tej książce informacje
były kompletne i rzetelne. Nie bierze jednak żadnej odpowiedzialności ani za ich wykorzystanie,
ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Wydawnictwo
HELION nie ponosi również żadnej odpowiedzialności za ewentualne szkody wynikłe
z wykorzystania informacji zawartych w książce.

Wydawnictwo HELION
ul. Kościuszki 1c, 44-100 GLIWICE
tel. 32 231 22 19, 32 230 98 63
e-mail: helion@helion.pl
WWW: http://helion.pl (księgarnia internetowa, katalog książek)

Pliki z przykładami omawianymi w książce można znaleźć pod adresem:
ftp://ftp.helion.pl/przyklady/proclo.zip

Drogi Czytelniku!
Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres
http://helion.pl/user/opinie/proclo
Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję.

Printed in Poland.

Kup książkę

Poleć książkę

Oceń książkę

Księgarnia internetowa

Lubię to! » Nasza społeczność

background image

Spis treci

Podzikowania ............................................................................................10

Przedmowa do wydania drugiego .............................................................11

Przedmowa do wydania pierwszego ........................................................13

Wstp ...........................................................................................................15

Rozdzia 1. Wprowadzenie .........................................................................23

1.1. Dlaczego Clojure? .............................................................................................24

1.2. Szybkie wprowadzenie do programowania w Clojure ...........................................34

1.3. Biblioteki jzyka Clojure .....................................................................................40

1.4. Podsumowanie ..................................................................................................44

Rozdzia 2. Przegld jzyka Clojure ..........................................................45

2.1. Konstrukcje skadniowe ......................................................................................46

2.2. Makra odczytu ...................................................................................................55

2.3. Funkcje .............................................................................................................56

2.4. Zmienne, wizania i przestrzenie nazw ...............................................................61

2.5. Wywoywanie kodu Javy .....................................................................................68

2.6. Przepyw sterowania ..........................................................................................70

2.7. Gdzie si podziaa ptla for? ..............................................................................74

2.8. Metadane ..........................................................................................................77

2.9. Podsumowanie ..................................................................................................79

Kup książkę

Poleć książkę

background image

8

Programowanie w jzyku Clojure

Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .......................81

3.1. Wszystko jest sekwencj .....................................................................................83

3.2. Stosowanie biblioteki sekwencji ...........................................................................87

3.3. Sekwencje nieskoczone i „leniwe” .....................................................................96

3.4. W Clojure Java jest sekwencyjna .........................................................................98

3.5. Funkcje przeznaczone dla konkretnych struktur ..................................................104

3.6. Podsumowanie ................................................................................................113

Rozdzia 4. Programowanie funkcyjne ...................................................115

4.1. Zagadnienia z obszaru programowania funkcyjnego ...........................................116

4.2. Jak stosowa „leniwe” podejcie? ......................................................................121

4.3. Leniwsze ni leniwe .........................................................................................130

4.4. Jeszcze o rekurencji ..........................................................................................136

4.5. Podsumowanie ................................................................................................146

Rozdzia 5. Stan .........................................................................................147

5.1. Wspóbieno, równolego i blokady .............................................................148

5.2. Referencje i pami STM ................................................................................150

5.3. Nieskoordynowane i synchroniczne aktualizacje za pomoc atomów ....................157

5.4. Stosowanie agentów do asynchronicznego aktualizowania danych .......................158

5.5. Zarzdzanie stanem specyficznym dla wtku za pomoc zmiennych ....................163

5.6. Gra Snake w jzyku Clojure .............................................................................168

5.7. Podsumowanie ................................................................................................178

Rozdzia 6. Protokoy i typy danych .......................................................179

6.1. Programowanie z wykorzystaniem abstrakcji ......................................................180

6.2. Interfejsy .........................................................................................................183

6.3. Protokoy ........................................................................................................184

6.4. Typy danych ...................................................................................................188

6.5. Rekordy ..........................................................................................................193

6.6. Makro reify .....................................................................................................198

6.7. Podsumowanie ................................................................................................199

Kup książkę

Poleć książkę

background image

Spis treci

9

Rozdzia 7. Makra .....................................................................................201

7.1. Kiedy naley stosowa makra? ..........................................................................202

7.2. Makro do sterowania przebiegiem programu ......................................................202

7.3. Upraszczanie makr ..........................................................................................209

7.4. Taksonomia makr ............................................................................................214

7.5. Podsumowanie ................................................................................................224

Rozdzia 8. Wielometody ..........................................................................225

8.1. ycie bez wielometod ......................................................................................226

8.2. Definiowanie wielometod .................................................................................228

8.3. Wicej ni proste wybieranie metod ...................................................................231

8.4. Tworzenie doranych taksonomii ......................................................................233

8.5. Kiedy naley korzysta z wielometod? ...............................................................237

8.6. Podsumowanie ................................................................................................241

Rozdzia 9. Sztuczki z Jav ......................................................................243

9.1. Obsuga wyjtków ............................................................................................244

9.2. Zmagania z liczbami cakowitymi .....................................................................248

9.3. Optymalizowanie wydajnoci ............................................................................250

9.4. Tworzenie klas Javy w jzyku Clojure ................................................................255

9.5. Praktyczny przykad .........................................................................................261

9.6. Podsumowanie ................................................................................................268

Rozdzia 10. Tworzenie aplikacji ............................................................269

10.1. Wynik w grze Clojurebreaker ..........................................................................270

10.2. Testowanie kodu zwracajcego wynik ..............................................................274

10.3. Biblioteka test.generative ................................................................................278

10.4. Tworzenie interfejsu .......................................................................................287

10.5. Instalowanie kodu ..........................................................................................292

10.6. Poegnanie ....................................................................................................295

Dodatek A. Edytory kodu .........................................................................297

Dodatek B. Bibliografia ............................................................................299

Skorowidz ..................................................................................................301

Kup książkę

Poleć książkę

background image

22

Programowanie w jzyku Clojure

Kup książkę

Poleć książkę

background image

Rozdzia 1.

Wprowadzenie

zybki wzrost popularnoci jzyka Clojure wynika z wielu przyczyn. Po krót-
kich poszukiwaniach w sieci WWW dowiesz si, e Clojure:



jest jzykiem funkcyjnym;



jest Lispem na maszyny JVM;



ma specjalne mechanizmy do obsugi wspóbienoci.

Wszystkie te cechy s wane, jednak adna z nich nie odgrywa najwaniejszej
roli. Naszym zdaniem najistotniejszymi aspektami jzyka Clojure s jego pro-
stota i moliwoci.

Prostota w kontekcie oprogramowania jest wana z kilku wzgldów, tu jednak
mamy na myli pierwotne i najwaniejsze znaczenie tego sowa — proste jest
to, co nie jest zoone. Proste komponenty umoliwiaj systemowi przeprowa-
dzanie operacji zaplanowanych przez projektantów i nie wykonuj czynnoci
niepowizanych z danym zadaniem. Z naszych dowiadcze wynika, e nie-
wielka zoono zwykle szybko przeksztaca si w niebezpiecznie powan.

Take sowo moliwoci ma wiele znacze. Tu mamy na myli zdolno do
wykonywania stawianych aplikacji zada. Aby programista mia odpowiednie
moliwoci, musi wykorzysta platform, która sama je posiada i jest powszechnie
dostpna. Tak platform jest na przykad maszyna JVM. Ponadto uywane
narzdzia musz zapewnia peny, nieograniczony dostp do oferowanych
moliwoci. Dostp do moliwoci jest czsto podstawowym wymogiem w pro-
jektach, w których trzeba w peni wykorzysta platform.

S

Kup książkę

Poleć książkę

background image

24

Programowanie w jzyku Clojure

Przez lata tolerowalimy bardzo skomplikowane narzdzia, które byy jedynym
sposobem na uzyskanie potrzebnych moliwoci. Czasem akceptowalimy te ogra-
niczone moliwoci w celu uproszczenia modelu programowania. Niekiedy nie da
si unikn pewnych kompromisów, jednak w obszarze moliwoci i prostoty nie
trzeba si z nimi godzi. Jzyk Clojure to dowód na to, e cechy te mona poczy.

1.1. Dlaczego Clojure?

Wszystkie charakterystyczne cechy jzyka Clojure maj zapewnia prostot,
moliwoci lub i jedno, i drugie. Oto kilka przykadów:



Programowanie funkcyjne jest proste, poniewa pozwala oddzieli ob-
liczenia od stanu i tosamoci. Zalet jest to, e programy funkcyjne s
atwiejsze do zrozumienia, pisania, testowania, optymalizowania i rów-
nolegego wykonywania.



Konstrukcje umoliwiajce wspódziaanie jzyków Clojure i Java daj
due moliwoci, poniewa zapewniaj bezporedni dostp do skadni
Javy. Zalet jest to, e mona uzyska wydajno na poziomie Javy
i stosowa skadni charakterystyczn dla tego jzyka. Co waniejsze,
nie trzeba ucieka si do jzyka niszego poziomu, aby zapewni sobie
dodatkowe moliwoci.



Lisp jest prosty w dwóch bardzo wanych aspektach — oddziela
wczytywanie od wykonania, a jego skadnia obejmuje niewielk liczb
niezalenych elementów. Zalet jest to, e wzorce projektowe s ujte
w abstrakcyjne konstrukcje skadniowe, a S-wyraenia obejmuj kod
w jzykach XML, JSON i SQL.



Lisp daje te due moliwoci, poniewa udostpnia kompilator i sys-
tem makr dziaajcy w czasie wykonywania programu. Zalet jest to, e
w Lispie wystpuje póne wizanie i mona atwo tworzy jzyki DSL.



Model czasu w jzyku Clojure jest prosty. Oddzielono w nim wartoci,
tosamo, stan i czas. Zalet jest to, e w programach mona spraw-
dza i zapamitywa informacje bez obaw o to, e starsze dane zostan
nadpisane.



Protokoy s proste. W Clojure polimorfizm jest niezaleny od dzie-
dziczenia. Zalet jest to, e mona bezpiecznie i w konkretnym celu
rozszerza typy oraz abstrakcje. Nie wymaga to stosowania zawiych
wzorców projektowych lub wprowadzania zmian w cudzym kodzie
(co czsto prowadzi do bdów).

Kup książkę

Poleć książkę

background image

Rozdzia 1. • Wprowadzenie

25

Ta lista cech stanowi „map” pomocn w dalszych rozdziaach ksiki. Nie
martw si, jeli na razie nie rozumiesz wszystkich szczegóów. Kadej z tych
cech powicamy cay rozdzia.

Zobaczmy, jak niektóre z tych cech sprawdzaj si w praktyce. Zbudujmy
w tym celu prost aplikacj. Przy okazji dowiesz si, jak wczytywa i wykony-
wa wiksze przykadowe programy, które prezentujemy dalej w ksice.

Jzyk Clojure jest elegancki

W jzyku Clojure stosunek sygnau do szumu jest wysoki. Dlatego programy
pisane w tym jzyku s krótkie. Takie programy s tasze w tworzeniu, insta-
lowaniu i konserwacji

1

. Jest to prawd zwaszcza wtedy, gdy programy s zwi-

ze, a nie tylko treciwe. Przyjrzyj si na przykad poniszemu kodowi w Javie
(pochodzi on z projektu Apache Commons):

data/snippets/isBlank.java

public class StringUtils {
public static boolean isBlank(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
}
}

Metoda

isBlank()

sprawdza, czy acuch znaków jest pusty (nie zawiera ad-

nych znaków lub obejmuje same odstpy). Oto kod podobnej metody w jzyku
Clojure:

src/examples/introduction.clj

(defn blank? [str]
(every? #(Character/isWhitespace %) str))

Wersja w jzyku Clojure jest krótsza, a co waniejsze — prostsza. Nie wyst-
puj tu zmienne, modyfikowalny stan ani rozgazienia. Efekt ten jest moliwy
dziki funkcjom wyszego rzdu. Funkcje tego rodzaju przyjmuj inne funkcje

1

Software Estimation: Demystifying the Black Art [McC06] to znakomita ksika.

Jej autorzy dowodz, e krótsze jest tasze.

Kup książkę

Poleć książkę

background image

26

Programowanie w jzyku Clojure

jako argumenty i (lub) zwracaj funkcje. Funkcja

every?

przyjmuje funkcj

i kolekcj, a zwraca warto

true

, jeli otrzymana funkcja zwraca

true

dla ka-

dego elementu z kolekcji.

Poniewa w wersji w jzyku Clojure nie ma rozgazie, kod jest bardziej czy-
telny i atwiejszy do przetestowania. Zalety te s jeszcze wyraniejsze w wik-
szych programach. Ponadto, cho kod jest zwizy, mona go atwo zrozumie.
Program w jzyku Clojure mona potraktowa jak definicj pustego acucha
znaków — jest to acuch, w którym kady znak jest odstpem. Kod ten jest
znacznie lepszy od metody z projektu Commons, w którym definicja pustego
acucha znaków jest ukryta za szczegóowym kodem ptli i instrukcji

if

.

Oto inny przykad. Przyjrzyj si banalnej klasie

Person

napisanej w jzyku Java:

data/snippets/Person.java

public class Person {
private String firstName;
private String lastName;

public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}
}

W jzyku Clojure rekord

Person

mona zdefiniowa w jednym wierszu:

(defrecord Person [first-name last-name])

Korzysta z tego rekordu mona tak:

(def foo (->Person "Aaron" "Bedra"))
-> #'user/foo
foo
-> #:user.Person{:first-name "Aaron", :last-name "Bedra"}

Kup książkę

Poleć książkę

background image

Rozdzia 1. • Wprowadzenie

27

Instrukcj

defrecord

i powizane funkcje omawiamy w podrozdziale 6.3,

„Protokoy”.

Kod w jzyku Clojure nie tylko jest znacznie krótszy; rekord

Person

jest tu nie-

zmienny. Niezmienne struktury danych s z natury bezpieczne ze wzgldu
na wtki, a mechanizmy modyfikowania danych mona utworzy w odrbnej
warstwie za pomoc referencji, agentów i atomów jzyka Clojure. Techniki te
omawiamy w rozdziale 5., „Stan”. Poniewa rekordy s niezmienne, jzyk
Clojure automatycznie udostpnia poprawne implementacje funkcji

hashCode()

i

equals()

.

Jzyk Clojure ma wbudowanych wiele eleganckich rozwiza, jeli jednak
stwierdzisz, e czego Ci w nim brakuje, moesz samodzielnie doda potrzebne
mechanizmy. Umoliwiaj to cechy Lispa.

Clojure to odwieony Lisp

Clojure jest Lispem. Od dziesicioleci zwolennicy Lispa mówi o przewagach,
jakie jzyk ten ma w porównaniu z waciwie wszystkimi innymi jzykami. Plan
opanowania wiata przez Lispa jest jednak realizowany do powoli.

Twórcy jzyka Clojure, podobnie jak autorzy kadej odmiany Lispa, musieli
zmierzy si z dwoma problemami. Oto one:



Clojure ma odnie sukces jako odmiana Lispa. Wymaga to przeko-
nania uytkowników Lispa, e Clojure obejmuje najwaniejsze mecha-
nizmy swojego poprzednika.



Jednoczenie Clojure ma odnie sukces tam, gdzie wczeniejsze wersje
Lispa si nie przyjy
. Wymaga to zdobycia poparcia wikszej spoecz-
noci programistów.

Autorzy jzyka Clojure radz sobie z tymi problemami przez udostpnienie me-
chanizmów metaprogramowania (charakterystycznych dla Lispa) i wprowadze-
nie zestawu usprawnie skadniowych uatwiajcych stosowanie jzyka Clojure
programistom, którzy nie znaj Lispa.

Dlaczego Lisp?

Wersje Lispa maj may rdze, s prawie pozbawione skadni i maj rozbudo-
wane mechanizmy do obsugi makr. Z uwagi na te cechy mona zmodyfikowa
Lispa pod ktem projektu, zamiast dostosowywa projekt do Lispa. Przyjrzyj si
poniszemu fragmentowi kodu w Javie:

Kup książkę

Poleć książkę

background image

28

Programowanie w jzyku Clojure

public class Person {
private String firstName;
public String getFirstName() {
// Cig dalszy.

W kodzie wystpuje metoda

getFirstName()

. Metody s polimorficzne i mona je

dostosowa do potrzeb. Jednak znaczenie kadego innego sowa w przykado-
wym kodzie jest okrelane przez jzyk. Czasem wygodna jest moliwo zmiany
znaczenia poszczególnych sów. Pozwala to na przykad:



zdefiniowa sowo

private

jako „prywatne w kodzie produkcyjnym, ale

publiczne na potrzeby serializacji i testów jednostkowych”;



zdefiniowa sowo

class

w taki sposób, aby platforma automatycznie

generowaa metody pobierajce i ustawiajce dla pól prywatnych (o ile
programista nie zarzdzi inaczej);



utworzy podklas dla

class

i umieci w niej wywoywane zwrotnie

uchwyty dla zdarze cyklu ycia; klasa z obsug cyklu ycia moe na
przykad zgasza zdarzenie utworzenia egzemplarza tej klasy.

Natykalimy si na programy, w których potrzebne byy wszystkie te cechy. Bez
potrzebnych mechanizmów programici musieli ucieka si do powtarzalnych
i podatnych na bdy sztuczek. Aby poradzi sobie z brakiem niezbdnych
rozwiza, napisano dosownie miliony wierszy kodu.

W wikszoci jzyków trzeba poprosi osoby odpowiedzialne za implementacj,
aby doday wspomniane wczeniej mechanizmy. W Clojure moesz samodzielnie
doda potrzebne cechy, piszc makra (rozdzia 7., „Makra”). Nawet sam jzyk
Clojure jest zbudowany za pomoc makr, takich jak

defrecord

:

(defrecord name [arg1 arg2 arg3])

Jeli chcesz zmieni znaczenie sowa, moesz napisa wasne makro. Jeeli
potrzebujesz rekordów o cisej kontroli typów i z opcjonalnym sprawdzaniem,
czy pola nie maj wartoci

null

, wystarczy utworzy wasne makro

defrecord

.

Powinno ono wyglda tak:

(defrecord name [Type :arg1 Type :arg2 Type :arg3]
:allow-nulls false)

Moliwo zmiany dziaania jzyka w nim samym jest wyjtkow zalet Lispa.
Mona znale wiele opisów rónych aspektów tego podejcia:



Lisp jest homoikoniczny

2

. Oznacza to, e kod w Lispie to dane. Dlatego

atwo jest tworzy programy za pomoc innych programów.

2

http://pl.wikipedia.org/wiki/homoikoniczno

Kup książkę

Poleć książkę

background image

Rozdzia 1. • Wprowadzenie

29



Cay jzyk jest dostpny w kadym momencie. Paul Graham w artykule
Revenge of the Nerds

3

wyjania, dlaczego jest to wane.

Skadnia Lispa eliminuje te problemy z priorytetami operatorów i cznoci
operacji. W ksice tej nie znajdziesz tabel dotyczcych tych zagadnie. Z uwagi
na wymóg stosowania nawiasów wyraenia s jednoznaczne.

Wad prostej, jednolitej skadni Lispa (przynajmniej dla pocztkujcych) jest
nacisk na nawiasy i listy (listy to gówny typ danych w Lispie). Clojure udo-
stpnia ciekawe poczenie cech, które uatwiaj uywanie Lispa programistom
znajcym inne jzyki.

Lisp z mniejsz liczb nawiasów

Clojure zapewnia istotne zalety programistom uywajcym innych odmian Lispa.
Oto te korzyci:



W jzyku Clojure fizyczne listy z Lispa s uogólnione do abstrakcyjnej
postaci — sekwencji. Pozwala to zachowa moliwoci, jakie daj listy,
a przy tym wykorzysta ich zalety w innych strukturach danych.



Wykorzystanie maszyn JVM jako podstawy dla kodu w jzyku Clojure
daje dostp do standardowej biblioteki i bardzo popularnej platformy.



Sposób analizowania symboli i cudzysowów sprawia, e w jzyku
Clojure pisanie standardowych makr jest stosunkowo proste.

Wielu uytkowników jzyka Clojure nie zna Lispa, za to prawdopodobnie
syszao niepochlebne opinie na temat stosowania w nim nawiasów. W jzyku
Clojure zachowano nawiasy (i moliwoci Lispa!), jednak pod kilkoma wzgl-
dami usprawniono tradycyjn skadni Lispa.



Clojure zapewnia wygodn, opart na literaach skadni dla rónych
struktur danych (nie tylko dla list), takich jak wyraenia regularne, od-
wzorowania, zbiory, wektory i metadane. Dlatego kod w jzyku Clojure
jest mniej zaleny od list ni w wikszoci innych odmian Lispa. Midzy
innymi parametry funkcji s podawane w wektorach,

[]

, a nie w listach,

()

.

src/examples/introduction.clj

(defn hello-world [username]
(println (format "Witaj, %s" username)))

Zastosowanie wektora sprawia, e lista argumentów jest lepiej widoczna,
co uatwia czytanie definicji funkcji w jzyku Clojure.

3

http://www.paulgraham.com/icad.html

Kup książkę

Poleć książkę

background image

30

Programowanie w jzyku Clojure



W jzyku Clojure, inaczej ni w wikszoci odmian Lispa, przecinki
s traktowane jak odstpy.

; Wektory przypominaj tablice z innych jzyków.
[1, 2, 3, 4]
-> [1 2 3 4]



Jzyk Clojure jest idiomatyczny i nie wymaga niepotrzebnego zagnie-
dania nawiasów. Przyjrzyj si makru

cond

, które wystpuje zarówno

w Common Lispie, jak i w Clojure. Makro

cond

sprawdza zestaw par

test-wynik i zwraca pierwszy wynik, dla którego warto wyraenia te-
stowego to

true

. Kada para test-wynik znajduje si w nawiasach:

; Makro cond w Common Lispie.
(cond ((= x 10) "equal")
((> x 10) "more"))

W jzyku Clojure dodatkowe nawiasy s niepotrzebne.

; Makro cond w Clojure.
(cond (= x 10) "equal"
(> x 10) "more")

Jest to kwestia czysto estetyczna i oba podejcia maj swoich zwolenników.
Wane jest to, e jzyk Clojure pozbawiono uciliwych aspektów Lispa,
jeli byo to moliwe bez utraty zalet tego ostatniego.

Clojure jest wietn odmian Lispa zarówno dla ekspertów, jak i dla poczt-
kujcych programistów Lispa.

Clojure to jzyk funkcyjny

Clojure jest jzykiem funkcyjnym, natomiast nie jest (w odrónieniu od Haskella)
czysto funkcyjny. Oto cechy jzyków funkcyjnych:



Funkcje to penoprawne obiekty. Oznacza to, e funkcje mona two-
rzy w czasie wykonywania programu, przekazywa, zwraca i ogólnie
uywa ich jak wszelkich innych typów danych.



Dane s niezmienne.



Funkcje s czyste, czyli nie maj efektów ubocznych.

W wielu obszarach programy funkcyjne s atwiejsze do zrozumienia, mniej
podatne na bdy i znacznie atwiejsze do wielokrotnego uytku. Na przykad
poniszy krótki program wyszukuje w bazie danych utwory kadego kompozy-
tora, który napisa dzieo pod tytuem „Requiem”:

(for [c compositions :when (= "Requiem" (:name c))] (:composer c))
-> ("W. A. Mozart" "Giuseppe Verdi")

Kup książkę

Poleć książkę

background image

Rozdzia 1. • Wprowadzenie

31

Sowo

for

nie jest pocztkiem ptli, ale wyraenia listowego (ang. list compre-

hension). Kod ten oznacza „dla kadego

c

z kolekcji

compositions

, gdzie nazw

c

jest

"Requiem"

, podaj kompozytora

c

”. Wyraenia listowe omawiamy w punkcie

„Przeksztacanie sekwencji”.

Przykadowy kod ma cztery podane cechy:



Jest prosty. Nie obejmuje ptli, zmiennych ani zmiennego stanu.



Jest bezpieczny ze wzgldu na wtki. Nie wymaga stosowania blokad.



Jest moliwy do równolegego wykonywania. Kady krok mona przy-
dzieli do odrbnego wtku bez koniecznoci modyfikowania kodu po-
szczególnych kroków.



Jest uniwersalny. Kolekcj

compositions

moe by zwyky zbiór, kod

w XML-u lub zbiór wyników z bazy danych.

Warto porówna programy funkcyjne z programami imperatywnymi, w których
instrukcje zmieniaj stan programu. Wikszo programów obiektowych pisze si
w stylu imperatywnym, dlatego nie maj one adnych z wymienionych wczeniej
zalet. S niepotrzebnie skomplikowane, niebezpieczne ze wzgldu na wtki, nie
umoliwiaj równolegego dziaania, a kod jest trudny do uogólnienia. Bezpo-
rednie porównanie podejcia funkcyjnego i imperatywnego znajdziesz w pod-
rozdziale 2.7, „Gdzie si podziaa ptla for?”.

Programici znaj zalety jzyków funkcyjnych ju od dugiego czasu. Jednak
jzyki funkcyjne, na przykad Haskell, nie zdobyy dominujcej pozycji. Wyni-
ka to z tego, e nie wszystkie operacje mona wygodnie wykona w podejciu
czysto funkcyjnym.

S cztery powody, dla których jzyk Clojure moe zyska wiksze zaintereso-
wanie ni dawne jzyki funkcyjne:



Podejcie funkcyjne jest dzi bardziej przydatne ni kiedykolwiek
wczeniej. Pojawiaj si maszyny o coraz wikszej liczbie rdzeni, a j-
zyki funkcyjne pozwalaj atwo wykorzysta moliwoci takiego sprztu.
Programowanie funkcyjne omawiamy w rozdziale 4., „Programowanie
funkcyjne”.



W jzykach funkcyjnych niewygodnie zarzdza si stanem, jeli musi
si on zmienia. Clojure udostpnia mechanizmy do obsugi zmien-
nego stanu za pomoc programowej pamici transakcyjnej i referencji,
agentów, atomów i wizania dynamicznego.

Kup książkę

Poleć książkę

background image

32

Programowanie w jzyku Clojure



W wielu jzykach funkcyjnych typy s okrelane statycznie. W jzyku
Clojure stosuje si dynamiczne okrelanie typów, co uatwia zadanie
programistom poznajcym dopiero programowanie funkcyjne.



Wywoywanie w jzyku Clojure kodu Javy nie odbywa si w modelu
funkcyjnym. Przy korzystaniu z Javy wkraczamy w znany wiat zmien-
nych obiektów. Zapewnia to wygod pocztkujcym, którzy ucz si
programowania funkcyjnego, a take pozwala w razie potrzeby zrezy-
gnowa z podejcia funkcyjnego. Wywoywanie kodu Javy opisujemy
w rozdziale 9., „Sztuczki z Jav”.

Mechanizmy zarzdzania zmian stanu w jzyku Clojure umoliwiaj pisanie
programów wspóbienych bez bezporedniego korzystania z blokad i uzupe-
niaj podstawowy funkcjonalny rdze jzyka.

Clojure upraszcza programowanie wspóbiene

Mechanizmy programowania funkcyjnego dostpne w Clojure uatwiaj pisanie
kodu bezpiecznego ze wzgldu na wtki. Poniewa niezmienne struktury danych
nigdy si nie zmieniaj, nie wystpuje zagroenie uszkodzeniem danych w wy-
niku dziaania innych wtków.

Jednak obsuga wspóbienoci w Clojure wykracza poza mechanizmy progra-
mowania funkcyjnego. Jeli potrzebne s referencje do zmiennych danych, Clojure
zabezpiecza je za pomoc programowej pamici transakcyjnej (ang. software
transactional memory
— STM). STM suy do tworzenia kodu bezpiecznego
ze wzgldu na wtki i jest rozwizaniem wyszego poziomu ni blokady z Javy.
Zamiast stosowa podatne na bdy strategie blokowania danych, mona za-
bezpieczy wspóuytkowany stan za pomoc transakcji. Jest to duo lepsze
podejcie, poniewa wielu programistów dobrze zna transakcje z uwagi na do-
wiadczenie w korzystaniu z baz danych.

Poniszy kod tworzy dziaajc, bezpieczn ze wzgldu na wtki baz danych
z kontami przechowywan w pamici:

(def accounts (ref #{}))
(defrecord Account [id balance])

Funkcja

ref

tworzy zabezpieczon za pomoc transakcji referencj do biecego

stanu bazy danych. Aktualizowanie stanu jest niezwykle proste. Poniej poka-
zujemy, jak doda do bazy nowe konto:

(dosync
(alter accounts conj (->Account "CLJ" 1000.00)))

Kup książkę

Poleć książkę

background image

Rozdzia 1. • Wprowadzenie

33

Instrukcja

dosync

powoduje aktualizowanie bazy

accounts

w transakcji. Rozwi-

zanie to zapewnia bezpieczestwo ze wzgldu na wtki i jest atwiejsze w sto-
sowaniu od blokad. Dziki transakcjom nigdy nie trzeba martwi si o to, które
obiekty i w jakiej kolejnoci naley zablokowa. Podejcie transakcyjne spraw-
dza si lepiej take w niektórych standardowych zastosowaniach. Przykadowo:
w modelu tym wtki wczytujce dane nigdy nie musz blokowa danych.

Cho przedstawiony przykad jest bardzo prosty, technika jest ogólna i spraw-
dza si take w praktyce. Wicej informacji o wspóbienoci i pamici STM
w jzyku Clojure znajdziesz w rozdziale 5., „Stan”.

Wykorzystanie maszyny JVM w Clojure

Clojure zapewnia przejrzysty, prosty i bezporedni dostp do Javy. W kodzie
mona bezporednio wywoa metody z dowolnego interfejsu API Javy:

(System/getProperties)
-> {java.runtime.name=Java(TM) SE Runtime Environment
... i wiele innych ...

Clojure obejmuje wiele skadniowych mechanizmów do wywoywania kodu
w Javie. Nie omawiamy tu ich szczegóowo (zobacz podrozdzia 2.5, „Wywo-
ywanie kodu w Javie”), warto jednak wspomnie, e w Clojure wystpuje mniej
kropek i mniej nawiasów ni w analogicznym kodzie Javy:

// Java
"hello".getClass().getProtectionDomain()

; Clojure
(.. "hello" getClass getProtectionDomain)

Clojure udostpnia proste funkcje do implementowania interfejsów Javy i two-
rzenia klas pochodnych od klas Javy. Ponadto wszystkie funkcje jzyka Clojure
obejmuj implementacj interfejsów

Callable

i

Runnable

. Dlatego mona atwo

przekaza ponisz funkcj anonimow do konstruktora klasy

Thread

Javy:

(.start (new Thread (fn [] (println "Witaj" (Thread/currentThread)))))
-> Witaj #<Thread Thread[Thread-0,5,main]>

Dziwne dane wyjciowe wynikaj ze sposobu wywietlania informacji o obiek-
tach Javy w jzyku Clojure.

Thread

to nazwa klasy danego obiektu, a czon

Thread[Thread-0,5,main]

to efekt wywoania metody

toString

obiektu.

(Zauwa, e w przedstawionym kodzie nowy wtek dziaa a do zakoczenia pracy,
natomiast jego dane wyjciowe mog w dziwny sposób przeplata si z wierszami
zachty rodowiska REPL. Nie jest to problem z jzykiem Clojure, a jedynie
wynik zapisywania danych do strumienia wyjcia przez wicej ni jeden wtek).

Kup książkę

Poleć książkę

background image

34

Programowanie w jzyku Clojure

Poniewa skadnia do wywoywania kodu Javy w Clojure jest przejrzysta i pro-
sta, zwykle uywa si Javy bezporednio, zamiast ukrywa kod w tym jzyku za
charakterystycznymi dla Lispa nakadkami.

Poznae ju kilka powodów do stosowania jzyka Clojure. Pora przystpi do
pisania kodu.

1.2. Szybkie wprowadzenie

do programowania w Clojure

Aby uruchomi rodowisko jzyka Clojure i kod z tej ksiki, potrzebujesz
dwóch rzeczy. Oto one:



rodowisko uruchomieniowe Javy. Pobierz

4

i zainstaluj Jav w wersji

5. lub nowszej. W wersji 6. znacznie poprawiono wydajno i system
informowania o wyjtkach, dlatego warto stosowa wanie j.



Leiningen

5

. Leiningen to narzdzie do zarzdzania zalenociami i uru-

chamiania operacji na kodzie. Jest to take najpopularniejsze w wiecie
jzyka Clojure narzdzie do wykonywania tych zada.

Leiningen posuy do zainstalowania jzyka Clojure i wszystkich elementów
wymaganych w przykadowym kodzie. Jeli masz ju zainstalowane narzdzie
Leiningen, wiesz zapewne, jak z niego korzysta. Jeeli jeszcze nie masz po-
trzebnej wiedzy, zapoznaj si z krótkim wprowadzeniem ze strony narzdzia
w serwisie GitHub

6

. Znajdziesz tam instrukcje dotyczce instalacji, a take pod-

stawowe informacje na temat uytkowania Leiningena. Nie musisz jednak uczy
si wszystkiego, poniewa w ksice opisujemy polecenia potrzebne do uru-
chomienia przykadów.

W trakcie pracy z ksik korzystaj z jzyka Clojure w wersji waciwej dla
przykadowego kodu. Po przeczytaniu ksiki moesz zastosowa si do in-
strukcji z ramki „Samodzielne budowanie jzyka Clojure” i zbudowa aktualn
wersj jzyka.

4

http://www.oracle.com/technetwork/java/javase/downloads/index.html

5

http://github.com/technomancy/leiningen

6

http://github.com/technomancy/leiningen

Kup książkę

Poleć książkę

background image

Rozdzia 1. • Wprowadzenie

35

W punkcie „Pobieranie przykadowego kodu”, znajdziesz instrukcje dotyczce
pobierania przykadowego kodu. Po cigniciu przykadowego kodu trzeba
uy Leiningena do pobrania zalenoci. W katalogu gównym z kodem wywoaj
nastpujc instrukcj:

lein deps

Samodzielne budowanie jzyka Clojure

Moliwe, e chcesz zbudowa jzyk Clojure na podstawie kodu ródo-
wego, aby uzyska nowe funkcje i wprowadzi poprawki bdów. Mona
zrobi to w nastpujcy sposób:

git clone git://github.com/clojure/clojure.git
cd clojure
mvn package

Przykadowy kod jest regularnie aktualizowany pod ktem nowych rozwi-
za wprowadzanych w jzyku Clojure. Zapoznaj si z plikiem README
w przykadowym kodzie, aby sprawdzi numer najnowszej wersji, dla
której sprawdzono kod.

Zalenoci s pobierane i umieszczane w odpowiednim miejscu. Moesz prze-
testowa zainstalowane narzdzia przez przejcie do katalogu z przykadowym
kodem i uruchomienie rodowiska REPL jzyka Clojure. Leiningen obejmuje
skrypt uruchomieniowy rodowiska REPL, który wczytuje jzyk Clojure wraz
z zalenociami potrzebnymi w dalszych rozdziaach.

lein repl

Po udanym uruchomieniu rodowiska REPL powinien pojawi si wiersz
zachty z tekstem

user=>

:

Clojure
user=>

Teraz jeste gotowy do wywietlenia tekstu „Witaj, wiecie”.

Korzystanie ze rodowiska REPL

Aby pokaza, jak korzysta ze rodowiska REPL, tworzymy kilka wersji kodu
wywietlajcego tekst „Witaj, wiecie”. Najpierw wpisz kod

(println "Witaj,

wiecie")

w wierszu zachty rodowiska REPL.

user=> (println "Witaj, wiecie")

-> Witaj, wiecie

Kup książkę

Poleć książkę

background image

36

Programowanie w jzyku Clojure

Drugi wiersz,

Witaj, wiecie

, to dane dane wyjciowe z konsoli.

Teraz umiemy kod w funkcji, która potrafi „zwraca si” do uytkownika po
imieniu.

(defn hello [name] (str "Witaj, " name))
-> #'user/hello

Rozómy ten kod na fragmenty. Oto one:

 defn

suy do definiowania funkcji;

 hello

to nazwa funkcji;



funkcja

hello

przyjmuje jeden argument,

name

;

 str

to wywoanie funkcji czcej dowoln list argumentów w acuch

znaków;

 defn

,

hello

,

name

i

str

to symbole, czyli nazwy prowadzce do rónych

elementów; dozwolone symbole opisujemy w punkcie „Symbole”.

Przyjrzyj si zwracanej wartoci,

#'user/hello

. Przedrostek

#'

oznacza, e

funkcj zapisano w zmiennej jzyka Clojure, a

user

to przestrze nazw, w której

znajduje si ta funkcja. Jest to domylna przestrze nazw w rodowisku REPL,
odpowiadajca domylnemu pakietowi w Javie. Na razie zmienne i przestrzenie
nazw nie maj znaczenia. Omawiamy je w podrozdziale 2.4, „Zmienne, wi-
zanie i przestrzenie nazw”.

Teraz mona wywoa funkcj

hello

i przekaza do niej imi.

user=> (hello "Janku")
-> "Witaj, Janku"

Jeli rodowisko REPL znajduje si w dziwnym stanie, najatwiej zamkn je
za pomoc kombinacji klawiszy Ctrl+C w systemie Windows lub Ctrl+D
w systemach uniksowych, a nastpnie ponownie uruchomi.

Specjalne zmienne

rodowisko REPL obejmuje szereg przydatnych zmiennych specjalnych. W czasie
pracy w rodowisku REPL wyniki obliczania trzech ostatnich wyrae znaj-
duj si w specjalnych zmiennych

*1

,

*2

i

*3

. Pozwala to na wygodn prac

w modelu iteracyjnym. Spróbujmy poczy kilka powita.

user=> (hello "Janku")
-> "Witaj, Janku"

user=> (hello "Clojure")
-> "Witaj, Clojure"

Kup książkę

Poleć książkę

background image

Rozdzia 1. • Wprowadzenie

37

Teraz mona zastosowa specjalne zmienne do poczenia wyników ostatnich
instrukcji.

(str *1 " i " *2)
-> "Witaj, Clojure i Witaj, Janku"

Popenienie bdu w rodowisku REPL prowadzi do zgoszenia wyjtku Javy
(z uwagi na zwizo szczegóy pomijamy). Niedozwolone jest na przykad
dzielenie przez zero.

user=> (/ 1 0)
-> ArithmeticException Divide by zero clojure.lang.Numbers.divide

Tu problem jest oczywisty, jednak czasem jest bardziej skomplikowany i po-
trzebujemy szczegóowego stosu wywoa. W specjalnej zmiennej

*e

znajduj

si informacje o ostatnim wyjtku. Poniewa wyjtki w Clojure s wyjtkami
Javy, mona wywietli stos wywoa za pomoc instrukcji

pst

(od ang. print

stacktrace, czyli wywietl stos wywoa)

7

.

user=> (pst)
-> ArithmeticException Divide by zero
| clojure.lang.Numbers.divide
| sun.reflect.NativeMethodAccessorImpl.invoke0
| sun.reflect.NativeMethodAccessorImpl.invoke
| sun.reflect.DelegatingMethodAccessorImpl.invoke
| java.lang.reflect.Method.invoke
| clojure.lang.Reflector.invokeMatchingMethod
| clojure.lang.Reflector.invokeStaticMethod
| user/eval1677
| clojure.lang.Compiler.eval
| clojure.lang.Compiler.eval
| clojure.core/eval

Wspódziaanie z Jav omawiamy w rozdziale 9., „Sztuczki z Jav”.

Jeli blok kodu jest zbyt dugi, aby mona go wygodnie wpisa w rodowisku
REPL, umie kod w pliku, a nastpnie wczytaj ten plik w rodowisku. Moesz
uy cieki bezwzgldnej lub poda j wzgldem miejsca uruchomienia rodo-
wiska REPL.

; Zapisz kod w pliku temp.clj, a nastpnie wywoaj instrukcj:
user
=> (load-file "temp.clj")

REPL to znakomite rodowisko do wypróbowywania pomysów i otrzymywania
natychmiastowych informacji zwrotnych. Aby jak najlepiej wykorzysta ksik,
w trakcie jej lektury nie zamykaj rodowiska REPL.

7

Instrukcja

pst

jest dostpna tylko w Clojure 1.3.0 i nowszych wersjach.

Kup książkę

Poleć książkę

background image

38

Programowanie w jzyku Clojure

Dodawanie stanu wspóuytkowanego

Funkcja

hello

z poprzedniego przykadu to czysta funkcja, czyli taka, której

dziaanie nie ma efektów ubocznych. Czyste funkcje atwo si pisze i testuje.
S take atwe do zrozumienia, dlatego w wielu sytuacjach warto je stosowa.

Jednak w wikszoci programów wystpuje wspóuytkowany stan, a do zarz-
dzania nim su funkcje typu impure (czyli takie, które nie s czyste). Dodajmy
do funkcji

hello

mechanizm ledzenia liczby uytkowników. Najpierw trzeba

utworzy struktur danych do przechowywania tej liczby. Uyjmy do tego zbioru.

#{}
-> #{}

#{}

to litera oznaczajcy pusty zbiór. Potrzebna jest te operacja

conj

.

(conj coll item)

Instrukcja

conj

(od ang. conjoin, czyli czy) tworzy now kolekcj z dodawanym

elementem. Doczmy element do zbioru, aby upewni si, e powstaje nowy zbiór.

(conj #{} "Janku")
-> #{"Janku"}

Tworzenie nowych zbiorów jest ju moliwe. Pora opracowa sposób na spraw-
dzanie aktualnego zbioru uytkowników. Clojure udostpnia kilka sucych do
tego typów referencyjnych. Najprostszym typem referencyjnym jest atom.

(atom initial-state)

Aby okreli nazw atomu, naley uy instrukcji

def

.

(def symbol initial-value?)

Instrukcja

def

przypomina polecenie

defn

, ale jest ogólniejsza. Przy jej uyciu

mona definiowa funkcje lub dane. Uyjmy sowa

atom

do utworzenia atomu

i instrukcji

def

do powizania atomu z nazw

visitors

.

(def visitors (atom #{}))
-> #'user/visitors

Aby zaktualizowa referencj, trzeba uy funkcji, na przykad

swap!

.

(swap! r update-fn & args)

Funkcja

swap!

przeprowadza operacj

update-fn

na referencji

r

i w razie potrzeby

uywa przy tym opcjonalnych argumentów

args

. Spróbujmy wstawi uytkow-

nika do kolekcji

visitors

, uywajc do aktualizowania funkcji

conj

.

(swap! visitors conj "Janku")
-> #{"Janku"}

Kup książkę

Poleć książkę

background image

Rozdzia 1. • Wprowadzenie

39

atom

to tylko jeden z kilku typów referencyjnych dostpnych w jzyku Clojure.

Wybór odpowiedniego typu referencyjnego nie jest prosty (zagadnienie to
omawiamy w rozdziale 5., „Stan”).

W dowolnym momencie mona sprawdzi zawarto pamici, do której prowadzi
referencja. Suy do tego instrukcja

deref

lub jej krótszy odpowiednik,

@

.

(deref visitors)
-> #{"Janku"}

@visitors
-> #{"Janku"}

Teraz mona zbudowa now, bardziej rozbudowan wersj funkcji

hello

.

src/examples/introduction.clj

(defn hello
"Wywietla powitanie na wyjciu, uywajc nazwy uytkownika.
Potrafi stwierdzi, e korzystae ju z programu.
"
[username]
(swap! visitors conj username)
(str "Witaj, " username))

Teraz sprawdmy, czy uytkownicy s poprawnie zapisywani w pamici.

(hello "Marku")
-> "Witaj, Marku"

@visitors
-> #{"Jacku" "Janku" "Marku"}

Na Twoim komputerze lista uytkowników bdzie prawdopodobnie inna. Na tym
wanie polega problem ze stanem. Efekty s róne w zalenoci od tego, kiedy
zaszy dane zdarzenia. Zrozumie funkcj mona na podstawie jej analizy.
Aby zrozumie stan, trzeba pozna ca histori dziaania programu.

Jeli to moliwe, unikaj przechowywania stanu. Jeeli jest to niemoliwe, dbaj
o to, aby stanem mona byo zarzdza. Uywaj do tego typów referencyjnych,
na przykad atomów. Atomy (i wszystkie inne typy referencyjne w Clojure) s
bezpieczne przy korzystaniu z wielu wtków i procesorów. Co lepsze, zapew-
nienie bezpieczestwa nie wymaga stosowania blokad, które bywaj skompli-
kowane w uyciu.

Na tym etapie powiniene umie ju wprowadza krótkie fragmenty kodu
w rodowisku REPL. Wprowadzanie wikszych porcji kodu odbywa si podob-
nie. Take biblioteki jzyka Clojure mona wczytywa i uruchamia z poziomu
rodowiska REPL. Dalej pokazujemy, jak to zrobi.

Kup książkę

Poleć książkę

background image

40

Programowanie w jzyku Clojure

1.3. Biblioteki jzyka Clojure

Kod jzyka Clojure jest umieszczony w bibliotekach. Kada biblioteka jzyka
Clojure znajduje si w przestrzeni nazw, która jest odpowiednikiem pakietu
Javy. Bibliotek jzyka Clojure mona wczyta za pomoc instrukcji

require

.

(require quoted-namespace-symbol)

Jeli programista da biblioteki o nazwie

clojure.java.io

, Clojure szuka pliku

o nazwie clojure/java/io.clj w ciece ze zmiennej

CLASSPATH

. Zobaczmy, jaki jest

tego efekt.

user=> (require 'clojure.java.io)
-> nil

Pocztkowy pojedynczy apostrof (

'

) jest niezbdny i suy do dosownego po-

dawania (ang. quoting) nazwy biblioteki (podawanie nazw omawiamy w pod-
rozdziale 2.2, „Makra odczytu”). Zwrócona warto

nil

oznacza powodzenie.

Przy okazji sprawd, czy moesz wczyta przykadowy kod do tego rozdziau
(bibliotek

examples.introduction

).

user=> (require 'examples.introduction)
-> nil

Biblioteka

examples.introduction

obejmuje implementacj generowania liczb

Fibonacciego. W jzykach funkcyjnych jest to tradycyjny program typu „Witaj,
wiecie”. Liczby Fibonacciego omawiamy szczegóowo w podrozdziale 4.2,
„»Leniwe« podejcie”. Na razie upewnij si, e moesz uruchomi przykadow
funkcj

fibs

. Wprowad poniszy wiersz kodu w rodowisku REPL, a otrzy-

masz 10 pierwszych liczb Fibonacciego.

(take 10 examples.introduction/fibs)
-> (0 1 1 2 3 5 8 13 21 34)

Jeli otrzymae 10 pierwszych liczb Fibonacciego (wymienionych powyej),
poprawnie zainstalowae przykadowy kod z ksiki.

Wszystkie przykady sprawdzilimy za pomoc testów jednostkowych (testy
znajduj si w katalogu examples/test). Samych testów nie omawiamy w ksice,
jednak mog okaza si przydatnym ródem wiedzy. Aby uruchomi testy jed-
nostkowe, uyj instrukcji

lein test

.

Kup książkę

Poleć książkę

background image

Rozdzia 1. • Wprowadzenie

41

Instrukcje require i use

Po zadaniu biblioteki jzyka Clojure za pomoc instrukcji

require

elementy

z biblioteki trzeba wskazywa za pomoc penej nazwy. Zamiast nazwy

fibs

trzeba uy okrelenia

examples.introduction/fibs

. Uruchom drugi egzemplarz

rodowiska REPL

8

i wprowad poniszy kod.

(require 'examples.introduction)
-> nil

(take 10 examples.introduction/fibs)
-> (0 1 1 2 3 5 8 13 21 34)

Wprowadzanie penych nazw szybko staje si kopotliwe. Moesz uy instrukcji

refer

dla przestrzeni nazw i odwzorowa wszystkie nazwy z tej przestrzeni na

biec przestrze nazw.

(refer quoted-namespace-symbol)

Wywoaj instrukcj

refer

dla przestrzeni

examples.introduction

i sprawd, czy

moesz bezporednio wywoa funkcj

fibs

.

(refer 'examples.introduction)
-> nil

(take 10 fibs)
-> (0 1 1 2 3 5 8 13 21 34)

Wygodna funkcja

use

pozwala wykona instrukcje

require

i

refer

w jednym kroku.

(use quoted-namespace-symbol)

W nowym rodowisku REPL wprowad nastpujce instrukcje.

(use 'examples.introduction)
-> nil

(take 10 fibs)
-> (0 1 1 2 3 5 8 13 21 34)

W trakcie pracy z przykadowym kodem z ksiki moesz wywoa instrukcj

require

lub

use

z opcj

:reload

, aby wymusi ponowne wczytanie biblioteki.

(use :reload 'examples.introduction)
-> nil

Opcja

:reload

jest przydatna, jeli wprowadzasz zmiany i chcesz sprawdzi ich

efekt bez ponownego uruchamiania rodowiska REPL.

8

Otwarcie nowego rodowiska REPL zapobiega konfliktom nazw midzy utworzonym

wczeniej kodem a funkcjami o tych samych nazwach z przykadowego kodu. W praktyce
nie stanowi to problemu. Zagadnienie to omawiamy w punkcie „Przestrzenie nazw”.

Kup książkę

Poleć książkę

background image

42

Programowanie w jzyku Clojure

Znajdowanie dokumentacji

Potrzebna dokumentacja czsto jest dostpna bezporednio w rodowisku REPL.
Najprostsz funkcj pomocnicz

9

jest

doc

.

(doc name)

Uyjmy funkcji

doc

do wywietlenia dokumentacji funkcji

str

.

user=> (doc str)
-------------------------
clojure.core/str
([] [x] [x & ys])
With no args, returns the empty string. With one arg x, returns
x.toString(). (str nil) returns the empty string. With more than
one arg, returns the concatenation of the str values of the args.

Pierwszy wiersz danych wyjciowych funkcji

doc

obejmuje pen nazw spraw-

dzanej funkcji. W drugim znajduj si argumenty generowane bezporednio
w kodzie. Wybrane czsto stosowane nazwy argumentów i ich zastosowanie
omawiamy w ramce „Zwyczajowe nazwy parametrów”. Dalsze wiersze obejmuj
acuch znaków dokumentacji, jeli jest on podany w definicji funkcji.

Zwyczajowe nazwy parametrów

acuchy znaków dokumentacji w funkcjach

reduce

i

areduce

obejmuj

szereg krótkich nazw parametrów. Oto niektórych z tych nazw i sposoby
ich stosowania.

Parametr

Zastosowanie

a

Tablica Javy

agt

Agent

coll

Kolekcja

expr

Wyraenie

f

Funkcja

idx

Indeks

r

Referencja

v

Wektor

val

Warto

Nazwy mog wydawa si krótkie, jednak jest tak nie bez powodu —
„dobre” nazwy czsto s ju „zajte” przez funkcje jzyka Clojure! Uy-
wanie dla parametrów nazw identycznych z nazwami funkcji jest dopusz-
czalne, ale uznaje si to za oznak zego stylu. Parametr zasania wtedy
funkcj, dlatego jest ona niedostpna, kiedy parametr znajduje si w za-
sigu programu. Dlatego nie naley nazywa referencji

ref

, agentów

agent

, a liczników —

count

, poniewa s to nazwy funkcji.

9

Tak naprawd

doc

to makro jzyka Clojure.

Kup książkę

Poleć książkę

background image

Rozdzia 1. • Wprowadzenie

43

acuch znaków dokumentacji mona doda do funkcji przez umieszczenie go
bezporednio po jej nazwie.

src/examples/introduction.clj

(defn hello
"Wywietla powitanie na wyjciu, uywajc nazwy uytkownika. "
[username]
(println (str "Witaj, " username))

Czasem nie znasz nazwy elementu, którego dokumentacji potrzebujesz. Funkcja

find-doc

wyszukuje informacje o wszystkich elementach, dla których dane wyj-

ciowe funkcji

doc

pasuj do przekazanego wyraenia regularnego lub acucha

znaków.

(find-doc s)

Za pomoc funkcji

find-doc

mona sprawdzi, w jaki sposób Clojure skraca

kolekcje.

user=> (find-doc "reduce")
-------------------------
clojure/areduce
([a idx ret init expr])
Macro
... Szczegóy pominito ...
-------------------------
clojure/reduce
([f coll] [f val coll])
... Szczegóy pominito ...

Funkcja

reduce

pozwala w skrócony sposób stosowa operacje do kolekcji

jzyka Clojure. Omawiamy j w punkcie „Przeksztacanie sekwencji”. Funkcja

areduce

wspódziaa z tablicami Javy, a opisujemy j w punkcie „Korzystanie

z kolekcji Javy”.

Dua cz jzyka Clojure jest napisana w nim samym, dlatego lektura jego
kodu ródowego to pouczajce zadanie. Kod ródowy funkcji jzyka Clojure
mona wywietli za pomoc instrukcji

source

z biblioteki

repl

.

(clojure.repl/source symbol)

Wywietlmy kod ródowy prostej funkcji

identity

.

(use 'clojure.repl)
(source identity)

-> (defn identity
"Returns its argument."
{:added "1.0"
:static true}
[x] x)

Kup książkę

Poleć książkę

background image

44

Programowanie w jzyku Clojure

Oczywicie, mona te uywa interfejsu API Reflection Javy. Metody

class

,

ancestors

,

instance?

i podobne pozwalaj sprawdzi model obiektowy Javy

i informuj na przykad o tym, e kolekcje jzyka Clojure s jednoczenie ko-
lekcjami Javy.

(ancestors (class [1 2 3]))

-> #{clojure.lang.ILookup clojure.lang.Sequential
java.lang.Object clojure.lang.Indexed
java.lang.Iterable clojure.lang.IObj
clojure.lang.IPersistentCollection
clojure.lang.IPersistentVector clojure.lang.AFn
java.lang.Comparable java.util.RandomAccess
clojure.lang.Associative
clojure.lang.APersistentVector clojure.lang.Counted
clojure.lang.Reversible clojure.lang.IPersistentStack
java.util.List clojure.lang.IEditableCollection
clojure.lang.IFn clojure.lang.Seqable
java.util.Collection java.util.concurrent.Callable
clojure.lang.IMeta java.io.Serializable java.lang.Runnable}

Internetow dokumentacj interfejsu API jzyka Clojure znajdziesz na stronie
http://clojure.github.com/clojure. W ramce widocznej w prawej czci tej strony
znajduj si odnoniki do wszystkich funkcji i makr. Po lewej stronie umiesz-
czono odnoniki do artykuów na temat rónych cech jzyka Clojure.

1.4. Podsumowanie

Wanie zakoczye szybki przegld jzyka Clojure. Poznae dajc due
moliwoci skadni tego jzyka i jego zwizki z Lispem, a take zobaczye, jak
atwe jest wywoywanie w Clojure kodu Javy.

Uruchomie jzyk Clojure w swoim rodowisku, a take napisae w rodowisku
REPL krótkie programy ilustrujce programowanie funkcyjne i sucy do obsugi
stanu model referencji. Pora przyjrze si caemu jzykowi.

Kup książkę

Poleć książkę

background image

Skorowidz

A

agenty, 158

bieca warto, 159
sprawdzanie poprawnoci, 160
transakcje, 161
tworzenie, 158
wykrywanie bdów, 160

algebra relacji, 110
Apache Ant, 244
atomy, 157

dereferencja, 157
tworzenie, 157
ustawienie wartoci, 157

B

biblioteki, 20, 40

dosowne podawanie nazwy, 40
drzewo waciwoci systemowych, 238
znajdowanie dokumentacji, 42

C

Clojure, 15, 23

aktualizacja, 261
aspekty, 23
biblioteki, 20, 40

drzewo waciwoci systemowych, 238
inspector, 238

Lazytest, 286
math.combinatorics, 275
Midje, 286
sekwencje, 87
test, 239
test.generative, 278

cechy jzyka, 24, 209
czytnik, 46

makra odczytu, 55

edytory kodów, 297
funkcje, 56

czyste, 38
dodawanie sugestii typów, 253
impure, 38
wywoanie, 56
wyszego rzdu, 25

Java, 15, 33, 243

dostp, 243
interfejsy, 183, 255
javadoc, 70
kompilacja AOT, 248
konstrukcja new, 68
korzystanie z kolekcji, 258
mechanizm wywoa zwrotnych, 256
parsery SAX, 255
rodowisko uruchomieniowe, 34
tworzenie klas, 255

Kup książkę

Poleć książkę

background image

302

Programowanie w jzyku Clojure

Clojure

Java

tworzenie poredników, 255
tworzenie tablic, 258
wykorzystanie moliwoci, 247
wywoywanie kodu, 68
wywoywanie metody, 69

jzyk funkcyjny, 30

cechy, 30

konstrukcje skadniowe, 24, 46
Leiningen, 34, 261
liczby cakowite, 248

operatory, 248

Lisp, 15, 24, 27
makra, 28, 201

taksonomia, 216

maszyny JVM, 29
metadane, 77
model czasu, 24
niezmienne struktury danych, 27
obsuga wyjtków, 244

kontrolowane wyjtki, 245
porzdkowanie zasobów, 245
reagowanie na wyjtki, 247

optymalizowanie wydajnoci, 250

dodawanie sugestii typów, 253
uywanie typów prostych, 250

pobieranie zalenoci, 261
poczenie z witryn, 261
programowanie, 16

funkcyjne, 18, 24, 115
ptle, 74
reguy, 120
wspóbiene, 32

protokoy, 24, 179, 184
przestrze nazw, 36, 61, 65
rejestrowanie informacji, 264
rekordy, 193
rozkadanie struktury, 63

moliwoci, 65

sekwencje, 29, 81

biblioteka, 87
cechy, 83

Java, 98
manipulowanie, 197
wymuszanie realizacji, 97
wyraenia listowe, 95

stan, 147

model aktualizacji, 163
model funkcyjny, 149
model referencyjny, 149

sterowanie przepywem, 70

instrukcje, 70
makra, 71
rekurencja, 72

rodowisko REPL, 35

zmienne specjalne, 36

tosamo, 147

typy referencyjne, 147

tworzenie aplikacji, 269

gra Clojurebreaker, 270

typy danych, 179, 188

cechy, 188

typy referencyjne, 38

atom, 38

warto, 147
wizania, 61
wielometody, 225
wspóbieno, 18, 32, 148

powody stosowania, 148
sytuacja wycigu, 149
zakleszczenie, 149

zmienne, 36, 61

cechy, 62

D

definicja pustego acucha znaków, 26
duck typing, 250

F

funkcje, 56

anonimowe, 58

konstrukcja, 59
powody tworzenia, 58
stosowanie, 61
unikanie, 223

Kup książkę

Poleć książkę

background image

Skorowidz

303

bez sprawdzania przepenienia, 251
czciowe wywoanie, 134
czyste, 38, 116

niezmienne dane, 116

dodawanie sugestii typów, 253
efekty uboczne, 71
funkcje wyszego rzdu, 25
leniwe, 127
liczba argumentów, 57
listy, 105
acuchy znaków dokumentacji, 42
odwzorowania, 53, 106

tworzenie, 108

operatory matematyczne, 47
predykaty, 52, 56
przejrzyste referencyjnie, 118

memoizacja, 119

rozwinicie funkcji, 135

implementacja, 135

sekwencje, 83

filtrowanie, 91
predykaty, 92
przeksztacanie, 93
tworzenie, 88
wyraenia regularne, 100

sowa kluczowe, 54
wektory, 105
wizania, 62

zasig leksykalny, 63

wywoanie, 47, 56

notacja przedrostkowa, 47
notacja wrostkowa, 47

zbiory, 109
zoone, 134

H

hermetyzacja, 119

efekty uboczne, 120

Heroku, 292

biblioteka, 293
git init, 293
git push, 294
plik Procfile, 292

polecenie heroku, 293
rejestracja konta, 292
repozytorium git, 293

I

instrukcje

add-points, 171
agent-errors, 160
alias, 233
alter, 152
assoc, 171
atom, 157
binding, 164
clear-agent-errors, 160
commute, 154
concat, 210
cond, 227
condp, 182
conj, 38, 86
cons, 83, 132, 171
def, 38, 61, 218
defmacro, 203
defmethod, 228
defmulti, 175, 228
defn, 57
defonce, 133
defrecord, 27, 54
deref, 39, 150
derive, 236
dir, 279
do, 71, 219
doall, 97
dosync, 33, 150
faux-curry, 135
file-seq, 101
first, 76, 83
fn, 58
for, 75
force, 221
if, 70, 202
import, 67, 199
in-ns, 66, 281
inspect-tree, 238

Kup książkę

Poleć książkę

background image

304

Programowanie w jzyku Clojure

instrukcje

lazy-cat, 129
lazy-seq, 142
lein deps, 261
lein test, 40
let, 212
line-seq, 102
loop, 72
loop/recur, 72
macroexpand, 207
map, 219
memoize, 165
next-counter, 155
partial, 134
partition, 132
prefer-method, 232
println, 116, 203
project, 112
proxy, 176
pst, 37
recur, 72, 120, 130
ref, 156
refer, 41
ref-set, 150
require, 40, 41, 279
reset!, 157
rest, 83
score print-table, 276
select, 112
send, 159
send-off, 161
seq, 101, 258
set, 90
set!, 167, 254
source, 43
start, 163
swap!, 158
take-while, 91
trampoline, 139
unless, 202
use, 41, 66
var, 62
with-open, 102

J

Java, 15, 16, 243

interfejsy, 183

wady, 183
zalety, 183

klasy

BigDecimal, 249
BigInteger, 249
Character, 50
ChunkedSeq, 84
Person, 26
Random, 68
StringUtils, 74
Thread, 33
WidgetFactory, 205

metody egzemplarza, 204
obsuga, 245
obsuga wyjtków, 244

kontrolowane wyjtki, 244
porzdkowanie zasobów, 245

sekwencje, 98

kolekcje sekwencyjne, 98

wywoywanie kodu, 68

K

kod gry Snake, 169

interfejs GUI, 169, 175

aktualizowanie, 175
defmulti, 175
fill-point, 175
game, 176
game-panel, 175
paint, 175
proxy, 176
tworzenie nowej gry, 176
wywietlanie wa i jabka, 175

model funkcyjny, 169

add-points, 170, 171
assoc, 171
cons, 171
dodawanie punktów, 170
eats?, 172

Kup książkę

Poleć książkę

background image

Skorowidz

305

head-overlaps-body?, 172
lose?, 172
move, 171
point-to-screen-rect, 171
ruch wa, 171
sprawdzanie warunków zwycistwa, 172
turn, 173
tworzenie nowego jabka, 171
tworzenie wa, 171
tworzenie zestawu staych, 169
win?, 172
wykrywanie zetknicia, 172
zjadanie jabka, 172
zmiana kierunku wa, 173

model zmiennego stanu, 169, 173

reset-game, 173
update-direction, 174
update-positions, 174
wyduanie wa, 174
zmiany pozycji wa i jabka, 173

konstrukcje skadniowe, 24

liczba, 46

BigDecimal, 48
BigInt, 48
cakowita, 48
Ratio, 48
wektor, 47
zmiennoprzecinkowa, 48

lista, 46, 47

wywoywanie funkcji, 47

acuch znaków, 46, 49

wywoanie, 50

odwzorowania, 46, 52

sekwencje, 85

rekordy, 52

wywoywanie, 54

sowo kluczowe, 46, 53
symbol, 46, 49
warto logiczna, 46

reguy dziaania, 51

warto nil, 46
wektory, 46

sekwencje, 84

zbiory, 46

sekwencje, 85

znak, 46

L

Leiningen, 34, 261

pobieranie zalenoci, 35
wtyczka lein-noir, 287

leniwe sekwencje, 121, 125

moment realizacji, 127

Lisp, 15, 24

M

makra, 28, 201

amap, 260
and, 207, 216
areduce, 260
assert, 222
bad-unless, 207
bench, 212
binding, 164, 221
chain, 209
comment, 217
cond, 30
czas kompilacji, 203
czas rozwijania makra, 203
declare, 137, 218
definterface, 183
defpartial, 288
defprotocol, 185
defrecord, 28, 193
defstruct, 218
deftype, 189
delay, 220
dosync, 221
dotimes, 250
extend-protocol, 186
extend-type, 186
for, 95
import-static, 220
is, 239
jzyk szablonów, 210

Kup książkę

Poleć książkę

background image

306

Programowanie w jzyku Clojure

makra

konstrukcje specjalne, 215
lazy-seq, 125
let, 221
letfn, 124
manipulowanie list, 210
ns, 67
obsuga kilku konstrukcji, 208
obsuga szablonów, 211

przechwytywanie symboli, 213
splicing unquote, 211
unquote, 211

przetwarzanie, 203
reguy stosowania, 202
reify, 198
rozwijanie, 206

rekurencyjne, 207
tworzenie, 212

sprawdzanie, 206
sterowanie przebiegiem programu, 202
tablice Javy, 260
taksonomia, 214

kategorie, 216

time, 212, 221
tworzenie, 203
tworzenie nazw, 212

nazwy lokalne, 214

tworzenie zmiennych, 218
unikanie funkcji anonimowych, 223
unless, 203
upraszczanie, 209
wartociowanie argumentów, 203, 206

nakadki, 221
odraczanie, 220
warunkowe, 216

when, 208
when-not, 202, 208
with-open, 221, 245
with-out-str, 221
wspódziaanie z Jav, 219
wzorzec projektowy, 205

makra odczytu, 55

dereferencja, 56

funkcja anonimowa, 56
komentarz, 55, 56
metadane, 56
podawanie zmiennych, 56
przytaczanie, 56
syntax-quote, 56
unquote, 56
unquote-slicing, 56
wzorzec wyraenia regularnego, 56

maszyny JVM, 15, 29

autorekurencja, 124
Clojure, 16
Java, 16

memoizacja, 165
metadane, 77

standardowe klucze, 78

model czasu, 24

N

niezmienne struktury danych, 27

O

optymalizacja TCO, 73, 123

P

pami STM, 32, 151

technika MVCC, 153
transakcje, 151

ACI, 151
aktualizacje, 151

polimorfizm, 231
programowa pami transakcyjna, Patrz
pami STM
programowanie, 16, 18, 31, 97, 148

funkcyjne, 18, 24, 30, 116

autorekurencja, 124
czyste funkcje, 116
definicje rekurencyjne, 121
leniwe podejcie, 118, 121
leniwe sekwencje, 121, 125
problemy rekurencyjne, 138
prosta rekurencja, 122

Kup książkę

Poleć książkę

background image

Skorowidz

307

reguy, 120
rekurencja, 118
rekurencja kocowa, 123
rekurencja wzajemna, 136
trwae struktury danych, 117
wielokrotne wykorzystanie kodu, 119
wspóuytkowanie struktur, 117
wyraenie listowe, 31
zalety, 119

imperatywne, 31
kod ptli, 74
prawidowy proces pisania kodu, 273
sekwencyjne, 97
testowanie kodu, 274

BDD, 286
generowanie danych testu, 279
podstawowe etapy, 278
programowe sprawdzanie poprawnoci,

280

przeprowadzanie testów, 276, 283
sprawdzanie poprawnoci danych

wyjciowych, 277

sprawdzanie poprawnoci kodu, 278
TDD, 286
testy jednostkowe, 286
testy regresji, 277
tworzenie danych wejciowych, 275
zgaszanie bdu, 284

wspóbiene, 148

powody stosowania, 148

wykorzystanie abstrakcji, 180

obsuga dodatkowych typów, 181
odczyt, 180
zapis, 180

protokoy, 24, 179, 184

zalety, 184

przestrze nazw, 36, 65

clojure.core, 66
clojure.string, 67
funkcje, 68
modyfikacja deklaracji, 264
myapp, 66
user, 36, 65
wizania, 65

R

referencje, 150

sprawdzanie poprawnoci, 156
transakcje, 150

ACID, 151
aktualizowanie informacji, 152
atomowe, 151
izolowane, 151
licznik, 155
pami STM, 151
skoordynowane, 151
spójne, 151
trwae, 151
warto wewntrztransakcyjna, 153
waciwoci, 151
zmiana encji, 150

tworzenie, 150

rekordy, 193

dodawanie metod, 195
dostp do pól, 194
implementacja protokou, 195
Note, 193
odwzorowania, 193
Person, 26
tworzenie, 193

rekurencja, 72, 118

autorekurencja, 124
definicje, 121

indukcja, 121
przypadek bazowy, 121

problemy rekurencyjne, 138
prosta rekurencja, 122
przyspieszanie, 143
rekurencja kocowa, 123

optymalizacja TCO, 123

rekurencja wzajemna, 136

memoizacja, 144
optymalizowanie, 139
przeksztacanie na autorekurencj, 138
zastpowanie leniwym podejciem, 141

Kup książkę

Poleć książkę

background image

308

Programowanie w jzyku Clojure

S

sekwencje, 29, 81

biblioteka, 86, 87

funkcje, 88

cechy, 83
filtrowanie, 91

funkcje, 91

funkcje, 83
into, 86
Java, 98
kolekcje sekwencyjne, 82, 98
niezmienne, 87
odwzorowania, 85
predykaty, 92
przeksztacanie, 93

funkcje, 93

strumienie, 102
system plików, 101

funkcje, 101

tryb leniwy, 86, 96

stosowanie, 97
zalety, 96

tworzenie, 88

funkcje, 88

wektory, 84
wymuszanie realizacji, 97
wyraenia regularne, 100

funkcje, 100

zbiory, 85

stan, 147

agenty, 147, 158

bieca warto, 159
sprawdzanie poprawnoci, 160
transakcje, 161
tworzenie, 158
wykrywanie bdów, 160

atomy, 147, 157

dereferencja, 157
tworzenie, 157
ustawienie wartoci, 157

model aktualizacji, 163
modele zarzdzania, 168

referencje, 147, 150

transakcje, 150
tworzenie, 150

wywoywane zwrotnie metody, 166
zmienne, 147, 163

rodowisko REPL, 35

zmienne specjalne, 36

T

tworzenie aplikacji, 269

instalowanie kodu, 292

git push, 292, 294
Heroku, 292
plik Procfile, 292

testowanie kodu wyniku, 274

defspec, 282
dir, 279
failures, 284
generate-test-data, 282
generowanie danych testu, 279
in-ns, 281
programowe sprawdzanie poprawnoci,

280

random-secret, 280
require, 279
score print-table, 276
score-inputs, 278
selections, 275
sprawdzanie poprawnoci danych

wyjciowych, 277

test dla danych wejciowych, 276
test-dirs, 283
test-namespaces, 283
test-vars, 283
testy regresji, 277
tworzenie danych wejciowych, 275
zgaszanie bdu, 284

tworzenie interfejsu, 287

board, 290
defpartial, 288
dodanie stanu, 287

Kup książkę

Poleć książkę

background image

Skorowidz

309

framework sieciowy, 287
interfejs gracza, 288
render, 290
session/flash-put!, 290
session/get, 287
session/put!, 287
session/remove!, 290

wynik, 270

exact-matches, 271
frequencies, 271
generowanie, 270
merge-with, 272
score, 273
select-keys, 272
unordered-matches, 272

typy danych, 179, 188

anonimowe egzemplarze, 198
cechy, 188
CryptoVault, 179, 188
definiowanie metod, 189
dostp do pól, 189
rekordy, 193
tworzenie, 189

typy referencyjne, 38

atom, 38

W

wizania, 62

bindings, 63
dynamiczne, 164

modyfikacje na odlego, 164

dynamicznie okrelany zasig, 164
funkcje, 62

zasig leksykalny, 63

lokalne, 164
mechanizm rozkadania struktury, 63
podstawowe, 61
przestrze nazw, 65
zmienne, 62

wielometody, 225

account-level, 235
assert-expr, 240
definiowanie, 228
dodawanie implementacji metod, 228
domylne dziaanie, 230
dorane taksonomie, 233

dziedziczenie, 236

mechanizm wybierania implementacji, 229
my-print, 228, 231
paint, 175
service-charge, 235
stosowanie, 237

reguy, 241

wybieranie metod, 229

dla typu kolekcji, 231
na podstawie typu pierwszego

argumentu, 231

rozwizywanie konfliktów, 232

wspóbieno, 32
wyraenie listowe, 94

elementy, 94

Z

zmienne, 36, 61, 163

aliasy, 62
cechy, 62
mechanizm rozkadania struktury, 63
metadane, 62
rodzaje definicji, 133
specjalne, 164

modyfikacje na odlego, 164

tworzenie, 133

makra, 218

wizania, 62

lokalne dla wtku, 164
podstawowe, 61

Kup książkę

Poleć książkę

background image

310

Programowanie w jzyku Clojure

Kup książkę

Poleć książkę

background image
background image

Wyszukiwarka

Podobne podstrony:
Programowanie w jezyku Clojure proclo
Programowanie w jezyku Clojure proclo 2
Programowanie w jezyku Clojure proclo 2
Programowanie w jezyku Clojure
informatyka programowanie w jezyku clojure stuart halloway ebook
Programowanie w jezyku Clojure
Programowanie w jezyku C dla chetnych A Poznanski
Programowanie w jezyku C FAQ prcfaq
Napisać program w języku c który zawiera
16-20, Ogólna struktura programu w języku Pascal, Ogólna struktura programu w języku Pascal
Programowanie w języku asemblera
Informatyka, Podstawy Programowania w jezyku C++, Podstawy Programowania w jezyku C++'
PAS03, Og˙lna struktura programu w jezyku PASCAL
A Poznański Programowanie w języku C dla chętnych
Oracle Database 10g Programowanie w jezyku PL SQL or10ps
Efektywne Programowanie W Języku Java
Przykładowe zadania na 2 kolokwium z programowania w języku C, Studia, PWR, 1 semestr, Podstawy prog

więcej podobnych podstron