informatyka programowanie w jezyku clojure stuart halloway ebook

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 tre$ci

Podzi kowania ............................................................................................10

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

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

Wst p ...........................................................................................................15

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

1.1. Dlaczego Clojure? .............................................................................................24
1.2. Szybkie wprowadzenie do programowania w Clojure ...........................................34
1.3. Biblioteki j(zyka Clojure .....................................................................................40
1.4. Podsumowanie ..................................................................................................44

Rozdzia# 2. Przegl$d j zyka Clojure ..........................................................45

2.1. Konstrukcje sk+adniowe ......................................................................................46
2.2. Makra odczytu ...................................................................................................55
2.3. Funkcje .............................................................................................................56
2.4. Zmienne, wi1zania i przestrzenie nazw ...............................................................61
2.5. Wywo+ywanie kodu Javy .....................................................................................68
2.6. Przep+yw sterowania ..........................................................................................70
2.7. Gdzie si( podzia+a p(tla for? ..............................................................................74
2.8. Metadane ..........................................................................................................77
2.9. Podsumowanie ..................................................................................................79

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

8

Programowanie w j"zyku Clojure

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

3.1. Wszystko jest sekwencj1 .....................................................................................83
3.2. Stosowanie biblioteki sekwencji ...........................................................................87
3.3. Sekwencje niesko5czone 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 stosowa8 „leniwe” podej9cie? ......................................................................121
4.3. Leniwsze ni; leniwe .........................................................................................130
4.4. Jeszcze o rekurencji ..........................................................................................136
4.5. Podsumowanie ................................................................................................146

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

5.1. Wspó+bie;no98, równoleg+o98 i blokady .............................................................148
5.2. Referencje i pami(8 STM ................................................................................150
5.3. Nieskoordynowane i synchroniczne aktualizacje za pomoc1 atomów ....................157
5.4. Stosowanie agentów do asynchronicznego aktualizowania danych .......................158
5.5. Zarz1dzanie stanem specyficznym dla w1tku za pomoc1 zmiennych ....................163
5.6. Gra Snake w j(zyku Clojure .............................................................................168
5.7. Podsumowanie ................................................................................................178

Rozdzia# 6. Protoko#y i typy danych .......................................................179

6.1. Programowanie z wykorzystaniem abstrakcji ......................................................180
6.2. Interfejsy .........................................................................................................183
6.3. Protoko+y ........................................................................................................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 tre'ci

!

9

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

7.1. Kiedy nale;y stosowa8 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. Wi(cej ni; proste wybieranie metod ...................................................................231
8.4. Tworzenie dora@nych taksonomii ......................................................................233
8.5. Kiedy nale;y korzysta8 z wielometod? ...............................................................237
8.6. Podsumowanie ................................................................................................241

Rozdzia# 9. Sztuczki z Jav$ ......................................................................243

9.1. Obs+uga wyj1tków ............................................................................................244
9.2. Zmagania z liczbami ca+kowitymi .....................................................................248
9.3. Optymalizowanie wydajno9ci ............................................................................250
9.4. Tworzenie klas Javy w j(zyku Clojure ................................................................255
9.5. Praktyczny przyk+ad .........................................................................................261
9.6. Podsumowanie ................................................................................................268

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

10.1. Wynik w grze Clojurebreaker ..........................................................................270
10.2. Testowanie kodu zwracaj1cego wynik ..............................................................274
10.3. Biblioteka test.generative ................................................................................278
10.4. Tworzenie interfejsu .......................................................................................287
10.5. Instalowanie kodu ..........................................................................................292
10.6. Po;egnanie ....................................................................................................295

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

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

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

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

22

Programowanie w j"zyku Clojure

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia# 1.

Wprowadzenie

zybki wzrost popularno9ci j(zyka Clojure wynika z wielu przyczyn. Po krót-

kich poszukiwaniach w sieci WWW dowiesz si(, ;e Clojure:

jest j(zykiem funkcyjnym;

jest Lispem na maszyny JVM;

ma specjalne mechanizmy do obs+ugi wspó+bie;no9ci.

Wszystkie te cechy s1 wa;ne, jednak ;adna z nich nie odgrywa najwa;niejszej

roli. Naszym zdaniem najistotniejszymi aspektami j(zyka Clojure s1 jego pro-

stota i mo;liwo9ci.
Prostota

w kontek9cie oprogramowania jest wa;na z kilku wzgl(dów, tu jednak

mamy na my9li pierwotne i najwa;niejsze znaczenie tego s+owa — proste jest

to, co nie jest z+o;one. Proste komponenty umo;liwiaj1 systemowi przeprowa-

dzanie operacji zaplanowanych przez projektantów i nie wykonuj1 czynno9ci

niepowi1zanych z danym zadaniem. Z naszych do9wiadcze5 wynika, ;e nie-

wielka z+o;ono98 zwykle szybko przekszta+ca si( w niebezpiecznie powa;n1.
Tak;e s+owo mo$liwo%ci ma wiele znacze5. Tu mamy na my9li zdolno98 do

wykonywania stawianych aplikacji zada5. Aby programista mia+ odpowiednie

mo;liwo9ci, musi wykorzysta8 platform(, która sama je posiada i jest powszechnie

dost(pna. Tak1 platform1 jest na przyk+ad maszyna JVM. Ponadto u;ywane

narz(dzia musz1 zapewnia8 pe+ny, nieograniczony dost(p do oferowanych

mo;liwo9ci. Dost(p do mo;liwo9ci jest cz(sto podstawowym wymogiem w pro-

jektach, w których trzeba w pe+ni wykorzysta8 platform(.

S

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

24

Programowanie w j"zyku Clojure

Przez lata tolerowali9my bardzo skomplikowane narz(dzia, które by+y jedynym

sposobem na uzyskanie potrzebnych mo;liwo9ci. Czasem akceptowali9my te; ogra-

niczone mo;liwo9ci w celu uproszczenia modelu programowania. Niekiedy nie da

si( unikn18 pewnych kompromisów, jednak w obszarze mo;liwo9ci i prostoty nie

trzeba si( z nimi godzi8. J(zyk Clojure to dowód na to, ;e cechy te mo;na po+1czy8.

1.1. Dlaczego Clojure?

Wszystkie charakterystyczne cechy j(zyka Clojure maj1 zapewnia8 prostot(,

mo;liwo9ci lub i jedno, i drugie. Oto kilka przyk+adów:

Programowanie funkcyjne jest proste, poniewa; pozwala oddzieli8 ob-

liczenia od stanu i to;samo9ci. Zalet1 jest to, ;e programy funkcyjne s1

+atwiejsze do zrozumienia, pisania, testowania, optymalizowania i rów-

noleg+ego wykonywania.

Konstrukcje umo;liwiaj1ce wspó+dzia+anie j(zyków Clojure i Java daj1

du;e mo;liwo9ci, poniewa; zapewniaj1 bezpo9redni dost(p do sk+adni

Javy. Zalet1 jest to, ;e mo;na uzyska8 wydajno98 na poziomie Javy

i stosowa8 sk+adni( charakterystyczn1 dla tego j(zyka. Co wa;niejsze,

nie trzeba ucieka8 si( do j(zyka ni;szego poziomu, aby zapewni8 sobie

dodatkowe mo;liwo9ci.

Lisp jest prosty w dwóch bardzo wa;nych aspektach — oddziela

wczytywanie od wykonania, a jego sk+adnia obejmuje niewielk1 liczb(

niezale;nych elementów. Zalet1 jest to, ;e wzorce projektowe s1 uj(te

w abstrakcyjne konstrukcje sk+adniowe, a S-wyra;enia obejmuj1 kod

w j(zykach XML, JSON i SQL.

Lisp daje te; du;e mo;liwo9ci, poniewa; udost(pnia kompilator i sys-

tem makr dzia+aj1cy w czasie wykonywania programu. Zalet1 jest to, ;e

w Lispie wyst(puje pó@ne wi1zanie i mo;na +atwo tworzy8 j(zyki DSL.

Model czasu w j(zyku Clojure jest prosty. Oddzielono w nim warto9ci,

to;samo98, stan i czas. Zalet1 jest to, ;e w programach mo;na spraw-

dza8 i zapami(tywa8 informacje bez obaw o to, ;e starsze dane zostan1

nadpisane.

Protoko+y s1 proste. W Clojure polimorfizm jest niezale;ny od dzie-

dziczenia. Zalet1 jest to, ;e mo;na bezpiecznie i w konkretnym celu

rozszerza8 typy oraz abstrakcje. Nie wymaga to stosowania zawi+ych

wzorców projektowych lub wprowadzania zmian w cudzym kodzie

(co cz(sto prowadzi do b+(dów).

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia+ 1. • Wprowadzenie

!

25

Ta lista cech stanowi „map(” pomocn1 w dalszych rozdzia+ach ksi1;ki. Nie

martw si(, je9li na razie nie rozumiesz wszystkich szczegó+ów. Ka;dej z tych

cech po9wi(camy ca+y rozdzia+.
Zobaczmy, jak niektóre z tych cech sprawdzaj1 si( w praktyce. Zbudujmy

w tym celu prost1 aplikacj(. Przy okazji dowiesz si(, jak wczytywa8 i wykony-

wa8 wi(ksze przyk+adowe programy, które prezentujemy dalej w ksi1;ce.

J1zyk Clojure jest elegancki

W j(zyku Clojure stosunek sygna+u do szumu jest wysoki. Dlatego programy

pisane w tym j(zyku s1 krótkie. Takie programy s1 ta5sze w tworzeniu, insta-

lowaniu i konserwacji

1

. Jest to prawd1 zw+aszcza wtedy, gdy programy s1 zwi(-

z+e, a nie tylko tre9ciwe. Przyjrzyj si( na przyk+ad poni;szemu 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 +a5cuch znaków jest pusty (nie zawiera ;ad-

nych znaków lub obejmuje same odst(py). Oto kod podobnej metody w j(zyku

Clojure:

src/examples/introduction.clj

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

Wersja w j(zyku Clojure jest krótsza, a co wa;niejsze — prostsza. Nie wyst(-

puj1 tu zmienne, modyfikowalny stan ani rozga+(zienia. Efekt ten jest mo;liwy

dzi(ki funkcjom wy$szego rz)du. Funkcje tego rodzaju przyjmuj1 inne funkcje

1

Software Estimation: Demystifying the Black Art [McC06] to znakomita ksi1;ka.

Jej autorzy dowodz1, ;e krótsze jest ta5sze.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

26

Programowanie w j"zyku Clojure

jako argumenty i (lub) zwracaj1 funkcje. Funkcja

every?

przyjmuje funkcj(

i kolekcj(, a zwraca warto98

true

, je9li otrzymana funkcja zwraca

true

dla ka;-

dego elementu z kolekcji.
Poniewa; w wersji w j(zyku Clojure nie ma rozga+(zie5, kod jest bardziej czy-

telny i +atwiejszy do przetestowania. Zalety te s1 jeszcze wyra@niejsze w wi(k-

szych programach. Ponadto, cho8 kod jest zwi(z+y, mo;na go +atwo zrozumie8.

Program w j(zyku Clojure mo;na potraktowa8 jak definicj) pustego +a5cucha

znaków — jest to +a5cuch, w którym ka;dy znak jest odst(pem. Kod ten jest

znacznie lepszy od metody z projektu Commons, w którym definicja pustego

+a5cucha znaków jest ukryta za szczegó+owym kodem p(tli i instrukcji

if

.

Oto inny przyk+ad. Przyjrzyj si( banalnej klasie

Person

napisanej w j(zyku 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 j(zyku Clojure rekord

Person

mo;na zdefiniowa8 w jednym wierszu:

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

Korzysta8 z tego rekordu mo;na 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 powi1zane funkcje omawiamy w podrozdziale 6.3,

„Protoko+y”.
Kod w j(zyku Clojure nie tylko jest znacznie krótszy; rekord

Person

jest tu nie-

zmienny

. Niezmienne struktury danych s1 z natury bezpieczne ze wzgl(du

na w1tki, a mechanizmy modyfikowania danych mo;na utworzy8 w odr(bnej

warstwie za pomoc1 referencji, agentów i atomów j(zyka Clojure. Techniki te

omawiamy w rozdziale 5., „Stan”. Poniewa; rekordy s1 niezmienne, j(zyk

Clojure automatycznie udost(pnia poprawne implementacje funkcji

hashCode()

i

equals()

.

J(zyk Clojure ma wbudowanych wiele eleganckich rozwi1za5, je9li jednak

stwierdzisz, ;e czego9 Ci w nim brakuje, mo;esz samodzielnie doda8 potrzebne

mechanizmy. Umo;liwiaj1 to cechy Lispa.

Clojure to od$wie2ony Lisp

Clojure jest Lispem. Od dziesi(cioleci zwolennicy Lispa mówi1 o przewagach,

jakie j(zyk ten ma w porównaniu z w+a9ciwie wszystkimi innymi j(zykami. Plan

opanowania 9wiata przez Lispa jest jednak realizowany do98 powoli.
Twórcy j(zyka Clojure, podobnie jak autorzy ka;dej odmiany Lispa, musieli

zmierzy8 si( z dwoma problemami. Oto one:

Clojure ma odnie98 sukces jako odmiana Lispa. Wymaga to przeko-

nania u;ytkowników Lispa, ;e Clojure obejmuje najwa;niejsze mecha-

nizmy swojego poprzednika.

Jednocze9nie Clojure ma odnie98 sukces tam, gdzie wcze%niejsze wersje

Lispa si) nie przyj)4y

. Wymaga to zdobycia poparcia wi(kszej spo+ecz-

no9ci programistów.

Autorzy j(zyka Clojure radz1 sobie z tymi problemami przez udost(pnienie me-

chanizmów metaprogramowania (charakterystycznych dla Lispa) i wprowadze-

nie zestawu usprawnie5 sk+adniowych u+atwiaj1cych stosowanie j(zyka Clojure

programistom, którzy nie znaj1 Lispa.

Dlaczego Lisp?

Wersje Lispa maj1 ma+y rdze5, s1 prawie pozbawione sk+adni i maj1 rozbudo-

wane mechanizmy do obs+ugi makr. Z uwagi na te cechy mo;na zmodyfikowa8

Lispa pod k1tem projektu, zamiast dostosowywa8 projekt do Lispa. Przyjrzyj si(

poni;szemu fragmentowi kodu w Javie:

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

28

Programowanie w j"zyku Clojure

public class

Person {

private String firstName;
public String getFirstName() {
// Ci$g dalszy.

W kodzie wyst(puje metoda

getFirstName()

. Metody s1 polimorficzne i mo;na je

dostosowa8 do potrzeb. Jednak znaczenie ka$dego innego s4owa w przyk+ado-

wym kodzie jest okre%lane przez j)zyk. Czasem wygodna jest mo;liwo98 zmiany

znaczenia poszczególnych s+ów. Pozwala to na przyk+ad:

zdefiniowa8 s+owo

private

jako „prywatne w kodzie produkcyjnym, ale

publiczne na potrzeby serializacji i testów jednostkowych”;

zdefiniowa8 s+owo

class

w taki sposób, aby platforma automatycznie

generowa+a metody pobieraj1ce i ustawiaj1ce dla pól prywatnych (o ile

programista nie zarz1dzi inaczej);

utworzy8 podklas( dla

class

i umie9ci8 w niej wywo+ywane zwrotnie

uchwyty dla zdarze5 cyklu ;ycia; klasa z obs+ug1 cyklu ;ycia mo;e na

przyk+ad zg+asza8 zdarzenie utworzenia egzemplarza tej klasy.

Natykali9my si( na programy, w których potrzebne by+y wszystkie te cechy. Bez

potrzebnych mechanizmów programi9ci musieli ucieka8 si( do powtarzalnych

i podatnych na b+(dy sztuczek. Aby poradzi8 sobie z brakiem niezb(dnych

rozwi1za5, napisano dos+ownie miliony wierszy kodu.
W wi(kszo9ci j(zyków trzeba poprosi8 osoby odpowiedzialne za implementacj(,

aby doda+y wspomniane wcze9niej mechanizmy. W Clojure mo;esz samodzielnie

doda8 potrzebne cechy, pisz1c makra (rozdzia+ 7., „Makra”). Nawet sam j(zyk

Clojure jest zbudowany za pomoc1 makr, takich jak

defrecord

:

(defrecord name [arg1 arg2 arg3])

Je9li chcesz zmieni8 znaczenie s+owa, mo;esz napisa8 w+asne makro. Je;eli

potrzebujesz rekordów o 9cis+ej kontroli typów i z opcjonalnym sprawdzaniem,

czy pola nie maj1 warto9ci

null

, wystarczy utworzy8 w+asne makro

defrecord

.

Powinno ono wygl1da8 tak:

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

Mo;liwo98 zmiany dzia+ania j(zyka w nim samym jest wyj1tkow1 zalet1 Lispa.

Mo;na znale@8 wiele opisów ró;nych aspektów tego podej9cia:

Lisp jest homoikoniczny

2

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

+atwo jest tworzy8 programy za pomoc1 innych programów.

2

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

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia+ 1. • Wprowadzenie

!

29

Ca+y j(zyk jest dost(pny w ka;dym momencie. Paul Graham w artykule

Revenge of the Nerds

3

wyja9nia, dlaczego jest to wa;ne.

Sk+adnia Lispa eliminuje te; problemy z priorytetami operatorów i +1czno9ci1

operacji. W ksi1;ce tej nie znajdziesz tabel dotycz1cych tych zagadnie5. Z uwagi

na wymóg stosowania nawiasów wyra;enia s1 jednoznaczne.
Wad1 prostej, jednolitej sk+adni Lispa (przynajmniej dla pocz1tkuj1cych) jest

nacisk na nawiasy i listy (listy to g+ówny typ danych w Lispie). Clojure udo-

st(pnia ciekawe po+1czenie cech, które u+atwiaj1 u;ywanie Lispa programistom

znaj1cym inne j(zyki.

Lisp z mniejsz4 liczb4 nawiasów

Clojure zapewnia istotne zalety programistom u;ywaj1cym innych odmian Lispa.

Oto te korzy9ci:

W j(zyku Clojure fizyczne listy z Lispa s1 uogólnione do abstrakcyjnej

postaci — sekwencji. Pozwala to zachowa8 mo;liwo9ci, jakie daj1 listy,

a przy tym wykorzysta8 ich zalety w innych strukturach danych.

Wykorzystanie maszyn JVM jako podstawy dla kodu w j(zyku Clojure

daje dost(p do standardowej biblioteki i bardzo popularnej platformy.

Sposób analizowania symboli i cudzys+owów sprawia, ;e w j(zyku

Clojure pisanie standardowych makr jest stosunkowo proste.

Wielu u;ytkowników j(zyka Clojure nie zna Lispa, za to prawdopodobnie

s+ysza+o niepochlebne opinie na temat stosowania w nim nawiasów. W j(zyku

Clojure zachowano nawiasy (i mo;liwo9ci Lispa!), jednak pod kilkoma wzgl(-

dami usprawniono tradycyjn1 sk+adni( Lispa.

Clojure zapewnia wygodn1, opart1 na litera+ach sk+adni( dla ró;nych

struktur danych (nie tylko dla list), takich jak wyra;enia regularne, od-

wzorowania, zbiory, wektory i metadane. Dlatego kod w j(zyku Clojure

jest mniej zale;ny od list ni; w wi(kszo9ci innych odmian Lispa. Mi(dzy

innymi parametry funkcji s1 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 u+atwia czytanie definicji funkcji w j(zyku Clojure.

3

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

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

30

Programowanie w j"zyku Clojure

W j(zyku Clojure, inaczej ni; w wi(kszo9ci odmian Lispa, przecinki

s1 traktowane jak odst(py.

; Wektory przypominaj$ tablice z innych j*zyków.
[1, 2, 3, 4]
-> [1 2 3 4]

J(zyk Clojure jest idiomatyczny i nie wymaga niepotrzebnego zagnie;-

d;ania nawiasów. Przyjrzyj si( makru

cond

, które wyst(puje zarówno

w Common Lispie, jak i w Clojure. Makro

cond

sprawdza zestaw par

test-wynik i zwraca pierwszy wynik, dla którego warto98 wyra;enia te-

stowego to

true

. Ka;da para test-wynik znajduje si( w nawiasach:

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

W j(zyku Clojure dodatkowe nawiasy s1 niepotrzebne.

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

Jest to kwestia czysto estetyczna i oba podej9cia maj1 swoich zwolenników.

Wa;ne jest to, ;e j(zyk Clojure pozbawiono uci1;liwych aspektów Lispa,

je9li by+o to mo;liwe bez utraty zalet tego ostatniego.

Clojure jest 9wietn1 odmian1 Lispa zarówno dla ekspertów, jak i dla pocz1t-

kuj1cych programistów Lispa.

Clojure to j1zyk funkcyjny

Clojure jest j(zykiem funkcyjnym, natomiast nie jest (w odró;nieniu od Haskella)

czysto funkcyjny. Oto cechy j(zyków funkcyjnych:

Funkcje to pe4noprawne obiekty. Oznacza to, ;e funkcje mo;na two-

rzy8 w czasie wykonywania programu, przekazywa8, zwraca8 i ogólnie

u;ywa8 ich jak wszelkich innych typów danych.

Dane s1 niezmienne.

Funkcje s1 czyste, czyli nie maj1 efektów ubocznych.

W wielu obszarach programy funkcyjne s1 +atwiejsze do zrozumienia, mniej

podatne na b+(dy i znacznie +atwiejsze do wielokrotnego u;ytku. Na przyk+ad

poni;szy krótki program wyszukuje w bazie danych utwory ka;dego kompozy-

tora, który napisa+ dzie+o pod tytu+em „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

S+owo

for

nie jest pocz1tkiem p(tli, ale wyra$enia listowego (ang. list compre-

hension

). Kod ten oznacza „dla ka;dego

c

z kolekcji

compositions

, gdzie nazw1

c

jest

"Requiem"

, podaj kompozytora

c

”. Wyra;enia listowe omawiamy w punkcie

„Przekszta+canie sekwencji”.
Przyk+adowy kod ma cztery po;1dane cechy:

Jest prosty. Nie obejmuje p(tli, zmiennych ani zmiennego stanu.

Jest bezpieczny ze wzgl)du na w?tki. Nie wymaga stosowania blokad.

Jest mo$liwy do równoleg4ego wykonywania. Ka;dy krok mo;na przy-

dzieli8 do odr(bnego w1tku bez konieczno9ci modyfikowania kodu po-

szczególnych kroków.

Jest uniwersalny. Kolekcj1

compositions

mo;e by8 zwyk+y zbiór, kod

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

Warto porówna8 programy funkcyjne z programami imperatywnymi, w których

instrukcje zmieniaj1 stan programu. Wi(kszo98 programów obiektowych pisze si(

w stylu imperatywnym, dlatego nie maj1 one $adnych z wymienionych wcze9niej

zalet. S1 niepotrzebnie skomplikowane, niebezpieczne ze wzgl(du na w1tki, nie

umo;liwiaj1 równoleg+ego dzia+ania, a kod jest trudny do uogólnienia. Bezpo-

9rednie porównanie podej9cia funkcyjnego i imperatywnego znajdziesz w pod-

rozdziale 2.7, „Gdzie si( podzia+a p(tla for?”.
Programi9ci znaj1 zalety j(zyków funkcyjnych ju; od d+ugiego czasu. Jednak

j(zyki funkcyjne, na przyk+ad Haskell, nie zdoby+y dominuj1cej pozycji. Wyni-

ka to z tego, ;e nie wszystkie operacje mo;na wygodnie wykona8 w podej9ciu

czysto funkcyjnym.
S1 cztery powody, dla których j(zyk Clojure mo;e zyska8 wi(ksze zaintereso-

wanie ni; dawne j(zyki funkcyjne:

Podej9cie funkcyjne jest dzi9 bardziej przydatne ni; kiedykolwiek

wcze9niej. Pojawiaj1 si( maszyny o coraz wi(kszej liczbie rdzeni, a j(-

zyki funkcyjne pozwalaj1 +atwo wykorzysta8 mo;liwo9ci takiego sprz(tu.

Programowanie funkcyjne omawiamy w rozdziale 4., „Programowanie

funkcyjne”.

W j(zykach funkcyjnych niewygodnie zarz1dza si( stanem, je9li musi

si( on zmienia8. Clojure udost(pnia mechanizmy do obs+ugi zmien-

nego stanu za pomoc1 programowej pami(ci transakcyjnej i referencji,

agentów, atomów i wi1zania dynamicznego.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

32

Programowanie w j"zyku Clojure

W wielu j(zykach funkcyjnych typy s1 okre9lane statycznie. W j(zyku

Clojure stosuje si( dynamiczne okre9lanie typów, co u+atwia zadanie

programistom poznaj1cym dopiero programowanie funkcyjne.

Wywo+ywanie w j(zyku Clojure kodu Javy nie odbywa si( w modelu

funkcyjnym. Przy korzystaniu z Javy wkraczamy w znany 9wiat zmien-

nych obiektów. Zapewnia to wygod( pocz1tkuj1cym, którzy ucz1 si(

programowania funkcyjnego, a tak;e pozwala w razie potrzeby zrezy-

gnowa8 z podej9cia funkcyjnego. Wywo+ywanie kodu Javy opisujemy

w rozdziale 9., „Sztuczki z Jav1”.

Mechanizmy zarz1dzania zmian1 stanu w j(zyku Clojure umo;liwiaj1 pisanie

programów wspó+bie;nych bez bezpo9redniego korzystania z blokad i uzupe+-

niaj1 podstawowy funkcjonalny rdze5 j(zyka.

Clojure upraszcza programowanie wspó7bie2ne

Mechanizmy programowania funkcyjnego dost(pne w Clojure u+atwiaj1 pisanie

kodu bezpiecznego ze wzgl(du na w1tki. Poniewa; niezmienne struktury danych

nigdy

si( nie zmieniaj1, nie wyst(puje zagro;enie uszkodzeniem danych w wy-

niku dzia+ania innych w1tków.
Jednak obs+uga wspó+bie;no9ci w Clojure wykracza poza mechanizmy progra-

mowania funkcyjnego. Je9li potrzebne s1 referencje do zmiennych danych, Clojure

zabezpiecza je za pomoc1 programowej pami(ci transakcyjnej (ang. software

transactional memory

— STM). STM s+u;y do tworzenia kodu bezpiecznego

ze wzgl(du na w1tki i jest rozwi1zaniem wy;szego poziomu ni; blokady z Javy.

Zamiast stosowa8 podatne na b+(dy strategie blokowania danych, mo;na za-

bezpieczy8 wspó+u;ytkowany stan za pomoc1 transakcji. Jest to du;o lepsze

podej9cie, poniewa; wielu programistów dobrze zna transakcje z uwagi na do-

9wiadczenie w korzystaniu z baz danych.
Poni;szy kod tworzy dzia+aj1c1, bezpieczn1 ze wzgl(du na w1tki baz( danych

z kontami przechowywan1 w pami(ci:

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

Funkcja

ref

tworzy zabezpieczon1 za pomoc1 transakcji referencj( do bie;1cego

stanu bazy danych. Aktualizowanie stanu jest niezwykle proste. Poni;ej poka-

zujemy, jak doda8 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. Rozwi1-

zanie to zapewnia bezpiecze5stwo ze wzgl(du na w1tki i jest +atwiejsze w sto-

sowaniu od blokad. Dzi(ki transakcjom nigdy nie trzeba martwi8 si( o to, które

obiekty i w jakiej kolejno9ci nale;y zablokowa8. Podej9cie transakcyjne spraw-

dza si( lepiej tak;e w niektórych standardowych zastosowaniach. Przyk+adowo:

w modelu tym w1tki wczytuj1ce dane nigdy nie musz1 blokowa8 danych.
Cho8 przedstawiony przyk+ad jest bardzo prosty, technika jest ogólna i spraw-

dza si( tak;e w praktyce. Wi(cej informacji o wspó+bie;no9ci i pami(ci STM

w j(zyku Clojure znajdziesz w rozdziale 5., „Stan”.

Wykorzystanie maszyny JVM w Clojure

Clojure zapewnia przejrzysty, prosty i bezpo9redni dost(p do Javy. W kodzie

mo;na bezpo9rednio wywo+a8 metody z dowolnego interfejsu API Javy:

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

Clojure obejmuje wiele sk+adniowych mechanizmów do wywo+ywania kodu

w Javie. Nie omawiamy tu ich szczegó+owo (zobacz podrozdzia+ 2.5, „Wywo-

+ywanie kodu w Javie”), warto jednak wspomnie8, ;e w Clojure wyst(puje mniej

kropek i mniej nawiasów ni; w analogicznym kodzie Javy:

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

; Clojure
(.. "hello" getClass getProtectionDomain)

Clojure udost(pnia proste funkcje do implementowania interfejsów Javy i two-

rzenia klas pochodnych od klas Javy. Ponadto wszystkie funkcje j(zyka Clojure

obejmuj1 implementacj( interfejsów

Callable

i

Runnable

. Dlatego mo;na +atwo

przekaza8 poni;sz1 funkcj( anonimow1 do konstruktora klasy

Thread

Javy:

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

Dziwne dane wyj9ciowe wynikaj1 ze sposobu wy9wietlania informacji o obiek-

tach Javy w j(zyku Clojure.

Thread

to nazwa klasy danego obiektu, a cz+on

Thread[Thread-0,5,main]

to efekt wywo+ania metody

toString

obiektu.

(Zauwa;, ;e w przedstawionym kodzie nowy w1tek dzia+a a; do zako5czenia pracy,

natomiast jego dane wyj9ciowe mog1 w dziwny sposób przeplata8 si( z wierszami

zach(ty 9rodowiska REPL. Nie jest to problem z j(zykiem Clojure, a jedynie

wynik zapisywania danych do strumienia wyj9cia przez wi(cej ni; jeden w1tek).

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

34

Programowanie w j"zyku Clojure

Poniewa; sk+adnia do wywo+ywania kodu Javy w Clojure jest przejrzysta i pro-

sta, zwykle u;ywa si( Javy bezpo9rednio, zamiast ukrywa8 kod w tym j(zyku za

charakterystycznymi dla Lispa nak+adkami.
Pozna+e9 ju; kilka powodów do stosowania j(zyka Clojure. Pora przyst1pi8 do

pisania kodu.

1.2. Szybkie wprowadzenie

do programowania w Clojure

Aby uruchomi8 9rodowisko j(zyka Clojure i kod z tej ksi1;ki, potrzebujesz

dwóch rzeczy. Oto one:

Brodowisko uruchomieniowe Javy

. Pobierz

4

i zainstaluj Jav( w wersji

5. lub nowszej. W wersji 6. znacznie poprawiono wydajno98 i system

informowania o wyj1tkach, dlatego warto stosowa8 w+a9nie j1.

Leiningen

5

. Leiningen to narz(dzie do zarz1dzania zale;no9ciami i uru-

chamiania operacji na kodzie. Jest to tak;e najpopularniejsze w 9wiecie

j(zyka Clojure narz(dzie do wykonywania tych zada5.

Leiningen pos+u;y do zainstalowania j(zyka Clojure i wszystkich elementów

wymaganych w przyk+adowym kodzie. Je9li masz ju; zainstalowane narz(dzie

Leiningen, wiesz zapewne, jak z niego korzysta8. Je;eli jeszcze nie masz po-

trzebnej wiedzy, zapoznaj si( z krótkim wprowadzeniem ze strony narz(dzia

w serwisie GitHub

6

. Znajdziesz tam instrukcje dotycz1ce instalacji, a tak;e pod-

stawowe informacje na temat u;ytkowania Leiningena. Nie musisz jednak uczy8

si( wszystkiego, poniewa; w ksi1;ce opisujemy polecenia potrzebne do uru-

chomienia przyk+adów.
W trakcie pracy z ksi1;k1 korzystaj z j(zyka Clojure w wersji w+a9ciwej dla

przyk+adowego kodu. Po przeczytaniu ksi1;ki mo;esz zastosowa8 si( do in-

strukcji z ramki „Samodzielne budowanie j(zyka Clojure” i zbudowa8 aktualn1

wersj( j(zyka.

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 przyk+adowego kodu”, znajdziesz instrukcje dotycz1ce

pobierania przyk+adowego kodu. Po 9ci1gni(ciu przyk+adowego kodu trzeba

u;y8 Leiningena do pobrania zale;no9ci. W katalogu g+ównym z kodem wywo+aj

nast(puj1c1 instrukcj(:

lein deps

Samodzielne budowanie j"zyka Clojure

Mo9liwe, 9e chcesz zbudowa@ jAzyk Clojure na podstawie kodu DródFo-
wego, aby uzyska@ nowe funkcje i wprowadzi@ poprawki bFAdów. Mo9na
zrobi@ to w nastApujJcy sposób:

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

clojure

mvn package

PrzykFadowy kod jest regularnie aktualizowany pod kJtem nowych rozwiJ-
zaL wprowadzanych w jAzyku Clojure. Zapoznaj siA z plikiem README
w przykFadowym kodzie, aby sprawdzi@ numer najnowszej wersji, dla
której sprawdzono kod.

Zale;no9ci s1 pobierane i umieszczane w odpowiednim miejscu. Mo;esz prze-

testowa8 zainstalowane narz(dzia przez przej9cie do katalogu z przyk+adowym

kodem i uruchomienie 9rodowiska REPL j(zyka Clojure. Leiningen obejmuje

skrypt uruchomieniowy 9rodowiska REPL, który wczytuje j(zyk Clojure wraz

z zale;no9ciami potrzebnymi w dalszych rozdzia+ach.

lein repl

Po udanym uruchomieniu 9rodowiska REPL powinien pojawi8 si( wiersz

zach(ty z tekstem

user=>

:

Clojure
user=>

Teraz jeste9 gotowy do wy9wietlenia tekstu „Witaj, 9wiecie”.

Korzystanie ze $rodowiska REPL

Aby pokaza8, jak korzysta8 ze 9rodowiska REPL, tworzymy kilka wersji kodu

wy9wietlaj1cego tekst „Witaj, 9wiecie”. Najpierw wpisz kod

(println "Witaj,

Mwiecie")

w wierszu zach(ty 9rodowiska REPL.

user=> (println "Witaj, Mwiecie")

-> Witaj, 3wiecie

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

36

Programowanie w j"zyku Clojure

Drugi wiersz,

Witaj, Mwiecie

, to ;1dane dane wyj9ciowe z konsoli.

Teraz umie98my kod w funkcji, która potrafi „zwraca8 si(” do u;ytkownika po

imieniu.

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

Roz+ó;my ten kod na fragmenty. Oto one:

defn

s+u;y do definiowania funkcji;

hello

to nazwa funkcji;

funkcja

hello

przyjmuje jeden argument,

name

;

str

to wywo+anie funkcji +1cz1cej dowoln1 list( argumentów w +a5cuch

znaków;

defn

,

hello

,

name

i

str

to symbole, czyli nazwy prowadz1ce do ró;nych

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

Przyjrzyj si( zwracanej warto9ci,

#'user/hello

. Przedrostek

#'

oznacza, ;e

funkcj( zapisano w zmiennej j(zyka Clojure, a

user

to przestrzeF nazw, w której

znajduje si( ta funkcja. Jest to domy9lna przestrze5 nazw w 9rodowisku REPL,

odpowiadaj1ca domy9lnemu pakietowi w Javie. Na razie zmienne i przestrzenie

nazw nie maj1 znaczenia. Omawiamy je w podrozdziale 2.4, „Zmienne, wi1-

zanie i przestrzenie nazw”.
Teraz mo;na wywo+a8 funkcj(

hello

i przekaza8 do niej imi(.

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

Je9li 9rodowisko REPL znajduje si( w dziwnym stanie, naj+atwiej zamkn18 je

za pomoc1 kombinacji klawiszy Ctrl+C w systemie Windows lub Ctrl+D

w systemach uniksowych, a nast(pnie ponownie uruchomi8.

Specjalne zmienne

]rodowisko REPL obejmuje szereg przydatnych zmiennych specjalnych. W czasie

pracy w 9rodowisku REPL wyniki obliczania trzech ostatnich wyra;e5 znaj-

duj1 si( w specjalnych zmiennych

*1

,

*2

i

*3

. Pozwala to na wygodn1 prac(

w modelu iteracyjnym. Spróbujmy po+1czy8 kilka powita5.

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

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

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia+ 1. • Wprowadzenie

!

37

Teraz mo;na zastosowa8 specjalne zmienne do po+1czenia wyników ostatnich

instrukcji.

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

Pope+nienie b+(du w 9rodowisku REPL prowadzi do zg+oszenia wyj1tku Javy

(z uwagi na zwi(z+o98 szczegó+y pomijamy). Niedozwolone jest na przyk+ad

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 wywo+a5. W specjalnej zmiennej

*e

znajduj1

si( informacje o ostatnim wyj1tku. Poniewa; wyj1tki w Clojure s1 wyj1tkami

Javy, mo;na wy9wietli8 stos wywo+a5 za pomoc1 instrukcji

pst

(od ang. print

stacktrace

, czyli wy9wietl stos wywo+a5)

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ó+dzia+anie z Jav1 omawiamy w rozdziale 9., „Sztuczki z Jav1”.
Je9li blok kodu jest zbyt d+ugi, aby mo;na go wygodnie wpisa8 w 9rodowisku

REPL, umie98 kod w pliku, a nast(pnie wczytaj ten plik w 9rodowisku. Mo;esz

u;y8 9cie;ki bezwzgl(dnej lub poda8 j1 wzgl(dem miejsca uruchomienia 9rodo-

wiska REPL.

; Zapisz kod w pliku temp.clj, a nast*pnie wywo2aj instrukcj*:
user
=> (load-file "temp.clj")

REPL to znakomite 9rodowisko do wypróbowywania pomys+ów i otrzymywania

natychmiastowych informacji zwrotnych. Aby jak najlepiej wykorzysta8 ksi1;k(,

w trakcie jej lektury nie zamykaj 9rodowiska REPL.

7

Instrukcja

pst

jest dost(pna tylko w Clojure 1.3.0 i nowszych wersjach.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

38

Programowanie w j"zyku Clojure

Dodawanie stanu wspó7u2ytkowanego

Funkcja

hello

z poprzedniego przyk+adu to czysta funkcja, czyli taka, której

dzia+anie nie ma efektów ubocznych. Czyste funkcje +atwo si( pisze i testuje.

S1 tak;e +atwe do zrozumienia, dlatego w wielu sytuacjach warto je stosowa8.
Jednak w wi(kszo9ci programów wyst(puje wspó+u;ytkowany stan, a do zarz1-

dzania nim s+u;1 funkcje typu impure (czyli takie, które nie s1 czyste). Dodajmy

do funkcji

hello

mechanizm 9ledzenia liczby u;ytkowników. Najpierw trzeba

utworzy8 struktur( danych do przechowywania tej liczby. U;yjmy do tego zbioru.

#{}
-> #{}

#{}

to litera+ oznaczaj1cy pusty zbiór. Potrzebna jest te; operacja

conj

.

(conj coll item)

Instrukcja

conj

(od ang. conjoin, czyli +1czy8) tworzy now1 kolekcj( z dodawanym

elementem. Do+1czmy element do zbioru, aby upewni8 si(, ;e powstaje nowy zbiór.

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

Tworzenie nowych zbiorów jest ju; mo;liwe. Pora opracowa8 sposób na spraw-

dzanie aktualnego zbioru u;ytkowników. Clojure udost(pnia kilka s+u;1cych do

tego typów referencyjnych. Najprostszym typem referencyjnym jest atom.

(atom initial-state)

Aby okre9li8 nazw( atomu, nale;y u;y8 instrukcji

def

.

(def symbol initial-value?)

Instrukcja

def

przypomina polecenie

defn

, ale jest ogólniejsza. Przy jej u;yciu

mo;na definiowa8 funkcje lub dane. U;yjmy s+owa

atom

do utworzenia atomu

i instrukcji

def

do powi1zania atomu z nazw1

visitors

.

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

Aby zaktualizowa8 referencj(, trzeba u;y8 funkcji, na przyk+ad

swap!

.

(swap! r update-fn & args)

Funkcja

swap!

przeprowadza operacj(

update-fn

na referencji

r

i w razie potrzeby

u;ywa przy tym opcjonalnych argumentów

args

. Spróbujmy wstawi8 u;ytkow-

nika do kolekcji

visitors

, u;ywaj1c 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 dost(pnych w j(zyku Clojure.

Wybór odpowiedniego typu referencyjnego nie jest prosty (zagadnienie to

omawiamy w rozdziale 5., „Stan”).
W dowolnym momencie mo;na sprawdzi8 zawarto98 pami(ci, do której prowadzi

referencja. S+u;y do tego instrukcja

deref

lub jej krótszy odpowiednik,

@

.

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

@visitors
-> #{"Janku"}

Teraz mo;na zbudowa8 now1, bardziej rozbudowan1 wersj( funkcji

hello

.

src/examples/introduction.clj

(defn hello
"Wy%wietla powitanie na wyj%ciu, u$ywaj?c nazwy u$ytkownika.
Potrafi stwierdzi7, $e korzysta4e% ju$ z programu.
"
[username]
(swap! visitors conj username)
(str "Witaj, " username))

Teraz sprawd@my, czy u;ytkownicy s1 poprawnie zapisywani w pami(ci.

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

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

Na Twoim komputerze lista u;ytkowników b(dzie prawdopodobnie inna. Na tym

w+a9nie polega problem ze stanem. Efekty s1 ró;ne w zale;no9ci od tego, kiedy

zasz+y dane zdarzenia. Zrozumie8 funkcj( mo;na na podstawie jej analizy.

Aby zrozumie8 stan, trzeba pozna8 ca+1 histori( dzia+ania programu.
Je9li to mo;liwe, unikaj przechowywania stanu. Je;eli jest to niemo;liwe, dbaj

o to, aby stanem mo;na by+o zarz1dza8. U;ywaj do tego typów referencyjnych,

na przyk+ad atomów. Atomy (i wszystkie inne typy referencyjne w Clojure) s1

bezpieczne przy korzystaniu z wielu w1tków i procesorów. Co lepsze, zapew-

nienie bezpiecze5stwa nie wymaga stosowania blokad, które bywaj1 skompli-

kowane w u;yciu.
Na tym etapie powiniene9 umie8 ju; wprowadza8 krótkie fragmenty kodu

w 9rodowisku REPL. Wprowadzanie wi(kszych porcji kodu odbywa si( podob-

nie. Tak;e biblioteki j(zyka Clojure mo;na wczytywa8 i uruchamia8 z poziomu

9rodowiska REPL. Dalej pokazujemy, jak to zrobi8.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

40

Programowanie w j"zyku Clojure

1.3. Biblioteki j1zyka Clojure

Kod j(zyka Clojure jest umieszczony w bibliotekach. Ka;da biblioteka j(zyka

Clojure znajduje si( w przestrzeni nazw, która jest odpowiednikiem pakietu

Javy. Bibliotek( j(zyka Clojure mo;na wczyta8 za pomoc1 instrukcji

require

.

(require quoted-namespace-symbol)

Je9li programista ;1da biblioteki o nazwie

clojure.java.io

, Clojure szuka pliku

o nazwie clojure/java/io.clj w 9cie;ce ze zmiennej

CLASSPATH

. Zobaczmy, jaki jest

tego efekt.

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

Pocz1tkowy pojedynczy apostrof (

'

) jest niezb(dny i s+u;y do dos4ownego po-

dawania

(ang. quoting) nazwy biblioteki (podawanie nazw omawiamy w pod-

rozdziale 2.2, „Makra odczytu”). Zwrócona warto98

nil

oznacza powodzenie.

Przy okazji sprawd@, czy mo;esz wczyta8 przyk+adowy kod do tego rozdzia+u

(bibliotek(

examples.introduction

).

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

Biblioteka

examples.introduction

obejmuje implementacj( generowania liczb

Fibonacciego. W j(zykach funkcyjnych jest to tradycyjny program typu „Witaj,

9wiecie”. Liczby Fibonacciego omawiamy szczegó+owo w podrozdziale 4.2,

„»Leniwe« podej9cie”. Na razie upewnij si(, ;e mo;esz uruchomi8 przyk+adow1

funkcj(

fibs

. Wprowad@ poni;szy wiersz kodu w 9rodowisku REPL, a otrzy-

masz 10 pierwszych liczb Fibonacciego.

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

Je9li otrzyma+e9 10 pierwszych liczb Fibonacciego (wymienionych powy;ej),

poprawnie zainstalowa+e9 przyk+adowy kod z ksi1;ki.
Wszystkie przyk+ady sprawdzili9my za pomoc1 testów jednostkowych (testy

znajduj1 si( w katalogu examples/test). Samych testów nie omawiamy w ksi1;ce,

jednak mog1 okaza8 si( przydatnym @ród+em wiedzy. Aby uruchomi8 testy jed-

nostkowe, u;yj instrukcji

lein test

.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia+ 1. • Wprowadzenie

!

41

Instrukcje require i use

Po za;1daniu biblioteki j(zyka Clojure za pomoc1 instrukcji

require

elementy

z biblioteki trzeba wskazywa8 za pomoc1 pe+nej nazwy. Zamiast nazwy

fibs

trzeba u;y8 okre9lenia

examples.introduction/fibs

. Uruchom drugi egzemplarz

9rodowiska REPL

8

i wprowad@ poni;szy kod.

(require 'examples.introduction)
-> nil

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

Wprowadzanie pe+nych nazw szybko staje si( k+opotliwe. Mo;esz u;y8 instrukcji

refer

dla przestrzeni nazw i odwzorowa8 wszystkie nazwy z tej przestrzeni na

bie;1c1 przestrze5 nazw.

(refer quoted-namespace-symbol)

Wywo+aj instrukcj(

refer

dla przestrzeni

examples.introduction

i sprawd@, czy

mo;esz bezpo9rednio wywo+a8 funkcj(

fibs

.

(refer 'examples.introduction)
-> nil

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

Wygodna funkcja

use

pozwala wykona8 instrukcje

require

i

refer

w jednym kroku.

(use quoted-namespace-symbol)

W nowym 9rodowisku REPL wprowad@ nast(puj1ce instrukcje.

(use 'examples.introduction)
-> nil

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

W trakcie pracy z przyk+adowym kodem z ksi1;ki mo;esz wywo+a8 instrukcj(

require

lub

use

z opcj1

:reload

, aby wymusi8 ponowne wczytanie biblioteki.

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

Opcja

:reload

jest przydatna, je9li wprowadzasz zmiany i chcesz sprawdzi8 ich

efekt bez ponownego uruchamiania 9rodowiska REPL.

8

Otwarcie nowego 9rodowiska REPL zapobiega konfliktom nazw mi(dzy utworzonym

wcze9niej kodem a funkcjami o tych samych nazwach z przyk+adowego 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 j"zyku Clojure

Znajdowanie dokumentacji

Potrzebna dokumentacja cz(sto jest dost(pna bezpo9rednio w 9rodowisku REPL.

Najprostsz1 funkcj1 pomocnicz1

9

jest

doc

.

(doc name)

U;yjmy funkcji

doc

do wy9wietlenia 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 wyj9ciowych funkcji

doc

obejmuje pe+n1 nazw( spraw-

dzanej funkcji. W drugim znajduj1 si( argumenty generowane bezpo9rednio

w kodzie. Wybrane cz(sto stosowane nazwy argumentów i ich zastosowanie

omawiamy w ramce „Zwyczajowe nazwy parametrów”. Dalsze wiersze obejmuj1

4aFcuch znaków dokumentacji

, je9li jest on podany w definicji funkcji.

Zwyczajowe nazwy parametrów

NaLcuchy znaków dokumentacji w funkcjach reduce i areduce obejmujJ
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

Wyra9enie

f

Funkcja

idx

Indeks

r

Referencja

v

Wektor

val

WartoX@

Nazwy mogJ wydawa@ siA krótkie, jednak jest tak nie bez powodu —
„dobre” nazwy czAsto sJ ju9 „zajAte” przez funkcje jAzyka Clojure! U9y-
wanie dla parametrów nazw identycznych z nazwami funkcji jest dopusz-
czalne, ale uznaje siA to za oznakA zFego stylu. Parametr zasFania wtedy
funkcjA, dlatego jest ona niedostApna, kiedy parametr znajduje siA w za-
siAgu programu. Dlatego nie nale9y nazywa@ referencji ref, agentów
agent, a liczników — count, poniewa9 sJ to nazwy funkcji.

9

Tak naprawd(

doc

to makro j(zyka Clojure.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Rozdzia+ 1. • Wprowadzenie

!

43

`a5cuch znaków dokumentacji mo;na doda8 do funkcji przez umieszczenie go

bezpo9rednio po jej nazwie.

src/examples/introduction.clj

(defn hello
"Wy%wietla powitanie na wyj%ciu, u$ywaj?c nazwy u$ytkownika. "
[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-

9ciowe funkcji

doc

pasuj1 do przekazanego wyra;enia regularnego lub +a5cucha

znaków.

(find-doc s)

Za pomoc1 funkcji

find-doc

mo;na sprawdzi8, w jaki sposób Clojure skraca

kolekcje.

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

Funkcja

reduce

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

j(zyka Clojure. Omawiamy j1 w punkcie „Przekszta+canie sekwencji”. Funkcja

areduce

wspó+dzia+a z tablicami Javy, a opisujemy j1 w punkcie „Korzystanie

z kolekcji Javy”.
Du;a cz(98 j(zyka Clojure jest napisana w nim samym, dlatego lektura jego

kodu @ród+owego to pouczaj1ce zadanie. Kod @ród+owy funkcji j(zyka Clojure

mo;na wy9wietli8 za pomoc1 instrukcji

source

z biblioteki

repl

.

(clojure.repl/source symbol)

Wy9wietlmy kod @ród+owy 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 j"zyku Clojure

Oczywi9cie, mo;na te; u;ywa8 interfejsu API Reflection Javy. Metody

class

,

ancestors

,

instance?

i podobne pozwalaj1 sprawdzi8 model obiektowy Javy

i informuj1 na przyk+ad o tym, ;e kolekcje j(zyka Clojure s1 jednocze9nie 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}

Internetow1 dokumentacj( interfejsu API j(zyka Clojure znajdziesz na stronie

http://clojure.github.com/clojure

. W ramce widocznej w prawej cz(9ci tej strony

znajduj1 si( odno9niki do wszystkich funkcji i makr. Po lewej stronie umiesz-

czono odno9niki do artyku+ów na temat ró;nych cech j(zyka Clojure.

1.4. Podsumowanie

W+a9nie zako5czy+e9 szybki przegl1d j(zyka Clojure. Pozna+e9 daj1c1 du;e

mo;liwo9ci sk+adni( tego j(zyka i jego zwi1zki z Lispem, a tak;e zobaczy+e9, jak

+atwe jest wywo+ywanie w Clojure kodu Javy.
Uruchomi+e9 j(zyk Clojure w swoim 9rodowisku, a tak;e napisa+e9 w 9rodowisku

REPL krótkie programy ilustruj1ce programowanie funkcyjne i s+u;1cy do obs+ugi

stanu model referencji. Pora przyjrze8 si( ca+emu j(zykowi.

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Skorowidz

A

agenty, 158

bie;1ca warto98, 159
sprawdzanie poprawno9ci, 160
transakcje, 161
tworzenie, 158
wykrywanie b+(dów, 160

algebra relacji, 110
Apache Ant, 244
atomy, 157

dereferencja, 157
tworzenie, 157
ustawienie warto9ci, 157

B

biblioteki, 20, 40

dos+owne podawanie nazwy, 40
drzewo w+a9ciwo9ci systemowych, 238
znajdowanie dokumentacji, 42

C

Clojure, 15, 23

aktualizacja, 261
aspekty, 23
biblioteki, 20, 40

drzewo w+a9ciwo9ci systemowych, 238
inspector, 238

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

cechy j(zyka, 24, 209
czytnik, 46

makra odczytu, 55

edytory kodów, 297
funkcje, 56

czyste, 38
dodawanie sugestii typów, 253
impure, 38
wywo+anie, 56
wy;szego rz(du, 25

Java, 15, 33, 243

dost(p, 243
interfejsy, 183, 255
javadoc, 70
kompilacja AOT, 248
konstrukcja new, 68
korzystanie z kolekcji, 258
mechanizm wywo+a5 zwrotnych, 256
parsery SAX, 255
9rodowisko uruchomieniowe, 34
tworzenie klas, 255

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

302

Programowanie w j"zyku Clojure

Clojure

Java

tworzenie po9redników, 255
tworzenie tablic, 258
wykorzystanie mo;liwo9ci, 247
wywo+ywanie kodu, 68
wywo+ywanie metody, 69

j(zyk funkcyjny, 30

cechy, 30

konstrukcje sk+adniowe, 24, 46
Leiningen, 34, 261
liczby ca+kowite, 248

operatory, 248

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

taksonomia, 216

maszyny JVM, 29
metadane, 77
model czasu, 24
niezmienne struktury danych, 27
obs+uga wyj1tków, 244

kontrolowane wyj1tki, 245
porz1dkowanie zasobów, 245
reagowanie na wyj1tki, 247

optymalizowanie wydajno9ci, 250

dodawanie sugestii typów, 253
u;ywanie typów prostych, 250

pobieranie zale;no9ci, 261
po+1czenie z witryn1, 261
programowanie, 16

funkcyjne, 18, 24, 115
p(tle, 74
regu+y, 120
wspó+bie;ne, 32

protoko+y, 24, 179, 184
przestrze5 nazw, 36, 61, 65
rejestrowanie informacji, 264
rekordy, 193
rozk+adanie struktury, 63

mo;liwo9ci, 65

sekwencje, 29, 81

biblioteka, 87
cechy, 83

Java, 98
manipulowanie, 197
wymuszanie realizacji, 97
wyra;enia listowe, 95

stan, 147

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

sterowanie przep+ywem, 70

instrukcje, 70
makra, 71
rekurencja, 72

9rodowisko REPL, 35

zmienne specjalne, 36

to;samo98, 147

typy referencyjne, 147

tworzenie aplikacji, 269

gra Clojurebreaker, 270

typy danych, 179, 188

cechy, 188

typy referencyjne, 38

atom, 38

warto98, 147
wi1zania, 61
wielometody, 225
wspó+bie;no98, 18, 32, 148

powody stosowania, 148
sytuacja wy9cigu, 149
zakleszczenie, 149

zmienne, 36, 61

cechy, 62

D

definicja pustego +a5cucha 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 przepe+nienia, 251
cz(9ciowe wywo+anie, 134
czyste, 38, 116

niezmienne dane, 116

dodawanie sugestii typów, 253
efekty uboczne, 71
funkcje wy;szego rz(du, 25
leniwe, 127
liczba argumentów, 57
listy, 105
+a5cuchy znaków dokumentacji, 42
odwzorowania, 53, 106

tworzenie, 108

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

memoizacja, 119

rozwini(cie funkcji, 135

implementacja, 135

sekwencje, 83

filtrowanie, 91
predykaty, 92
przekszta+canie, 93
tworzenie, 88
wyra;enia regularne, 100

s+owa kluczowe, 54
wektory, 105
wi1zania, 62

zasi(g leksykalny, 63

wywo+anie, 47, 56

notacja przedrostkowa, 47
notacja wrostkowa, 47

zbiory, 109
z+o;one, 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 j"zyku 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
obs+uga, 245
obs+uga wyj1tków, 244

kontrolowane wyj1tki, 244
porz1dkowanie zasobów, 245

sekwencje, 98

kolekcje sekwencyjne, 98

wywo+ywanie 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
wy9wietlanie w(;a i jab+ka, 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 w(;a, 171
sprawdzanie warunków zwyci(stwa, 172
turn, 173
tworzenie nowego jab+ka, 171
tworzenie w(;a, 171
tworzenie zestawu sta+ych, 169
win?, 172
wykrywanie zetkni(cia, 172
zjadanie jab+ka, 172
zmiana kierunku w(;a, 173

model zmiennego stanu, 169, 173

reset-game, 173
update-direction, 174
update-positions, 174
wyd+u;anie w(;a, 174
zmiany pozycji w(;a i jab+ka, 173

konstrukcje sk+adniowe, 24

liczba, 46

BigDecimal, 48
BigInt, 48
ca+kowita, 48
Ratio, 48
wektor, 47
zmiennoprzecinkowa, 48

lista, 46, 47

wywo+ywanie funkcji, 47

+a5cuch znaków, 46, 49

wywo+anie, 50

odwzorowania, 46, 52

sekwencje, 85

rekordy, 52

wywo+ywanie, 54

s+owo kluczowe, 46, 53
symbol, 46, 49
warto98 logiczna, 46

regu+y dzia+ania, 51

warto98 nil, 46
wektory, 46

sekwencje, 84

zbiory, 46

sekwencje, 85

znak, 46

L

Leiningen, 34, 261

pobieranie zale;no9ci, 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
j(zyk szablonów, 210

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

306

Programowanie w j"zyku Clojure

makra

konstrukcje specjalne, 215
lazy-seq, 125
let, 221
letfn, 124
manipulowanie list1, 210
ns, 67
obs+uga kilku konstrukcji, 208
obs+uga szablonów, 211

przechwytywanie symboli, 213
splicing unquote, 211
unquote, 211

przetwarzanie, 203
regu+y 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
warto9ciowanie argumentów, 203, 206

nak+adki, 221
odraczanie, 220
warunkowe, 216

when, 208
when-not, 202, 208
with-open, 221, 245
with-out-str, 221
wspó+dzia+anie z Jav1, 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 wyra;enia 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(8 STM, 32, 151

technika MVCC, 153
transakcje, 151

ACI, 151
aktualizacje, 151

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

funkcyjne, 18, 24, 30, 116

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

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Skorowidz

! 307

regu+y, 120
rekurencja, 118
rekurencja ko5cowa, 123
rekurencja wzajemna, 136
trwa+e struktury danych, 117
wielokrotne wykorzystanie kodu, 119
wspó+u;ytkowanie struktur, 117
wyra;enie listowe, 31
zalety, 119

imperatywne, 31
kod p(tli, 74
prawid+owy proces pisania kodu, 273
sekwencyjne, 97
testowanie kodu, 274

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

280

przeprowadzanie testów, 276, 283
sprawdzanie poprawno9ci danych

wyj9ciowych, 277

sprawdzanie poprawno9ci kodu, 278
TDD, 286
testy jednostkowe, 286
testy regresji, 277
tworzenie danych wej9ciowych, 275
zg+aszanie b+(du, 284

wspó+bie;ne, 148

powody stosowania, 148

wykorzystanie abstrakcji, 180

obs+uga dodatkowych typów, 181
odczyt, 180
zapis, 180

protoko+y, 24, 179, 184

zalety, 184

przestrze5 nazw, 36, 65

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

R

referencje, 150

sprawdzanie poprawno9ci, 156
transakcje, 150

ACID, 151
aktualizowanie informacji, 152
atomowe, 151
izolowane, 151
licznik, 155
pami(8 STM, 151
skoordynowane, 151
spójne, 151
trwa+e, 151
warto98 wewn1trztransakcyjna, 153
w+a9ciwo9ci, 151
zmiana encji, 150

tworzenie, 150

rekordy, 193

dodawanie metod, 195
dost(p do pól, 194
implementacja protoko+u, 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 ko5cowa, 123

optymalizacja TCO, 123

rekurencja wzajemna, 136

memoizacja, 144
optymalizowanie, 139
przekszta+canie na autorekurencj(, 138
zast(powanie leniwym podej9ciem, 141

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

308

Programowanie w j"zyku 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
przekszta+canie, 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
wyra;enia regularne, 100

funkcje, 100

zbiory, 85

stan, 147

agenty, 147, 158

bie;1ca warto98, 159
sprawdzanie poprawno9ci, 160
transakcje, 161
tworzenie, 158
wykrywanie b+(dów, 160

atomy, 147, 157

dereferencja, 157
tworzenie, 157
ustawienie warto9ci, 157

model aktualizacji, 163
modele zarz1dzania, 168

referencje, 147, 150

transakcje, 150
tworzenie, 150

wywo+ywane zwrotnie metody, 166
zmienne, 147, 163

I

9rodowisko 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 poprawno9ci,

280

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

wyj9ciowych, 277

test dla danych wej9ciowych, 276
test-dirs, 283
test-namespaces, 283
test-vars, 283
testy regresji, 277
tworzenie danych wej9ciowych, 275
zg+aszanie b+(du, 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
dost(p do pól, 189
rekordy, 193
tworzenie, 189

typy referencyjne, 38

atom, 38

W

wi1zania, 62

bindings, 63
dynamiczne, 164

modyfikacje na odleg+o98, 164

dynamicznie okre9lany zasi(g, 164
funkcje, 62

zasi(g leksykalny, 63

lokalne, 164
mechanizm rozk+adania struktury, 63
podstawowe, 61
przestrze5 nazw, 65
zmienne, 62

wielometody, 225

account-level, 235
assert-expr, 240
definiowanie, 228
dodawanie implementacji metod, 228
domy9lne dzia+anie, 230
dora@ne taksonomie, 233

dziedziczenie, 236

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

regu+y, 241

wybieranie metod, 229

dla typu kolekcji, 231
na podstawie typu pierwszego

argumentu, 231

rozwi1zywanie konfliktów, 232

wspó+bie;no98, 32
wyra;enie listowe, 94

elementy, 94

Z

zmienne, 36, 61, 163

aliasy, 62
cechy, 62
mechanizm rozk+adania struktury, 63
metadane, 62
rodzaje definicji, 133
specjalne, 164

modyfikacje na odleg+o98, 164

tworzenie, 133

makra, 218

wi1zania, 62

lokalne dla w1tku, 164
podstawowe, 61

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ

background image

Czytaj dalej...

310

Programowanie w j"zyku Clojure

Kup ksi

ąĪkĊ

Pole

ü ksiąĪkĊ


Wyszukiwarka

Podobne podstrony:
informatyka programowanie w jezyku java zbior zadan z p odpowiedziami wieslaw rychlicki ebook
Programowanie w jezyku Clojure proclo
Programowanie w jezyku Clojure proclo 2
Programowanie w jezyku Clojure proclo 2
informatyka programowanie obiektowe w php 5 hasin hayder ebook
Programowanie w jezyku Clojure
Programowanie w jezyku Clojure
Programowanie w jezyku Clojure 2
Informatyka, Podstawy Programowania w jezyku C++, Podstawy Programowania w jezyku C++'
infa wykłady Programowanie w języku C# Informatyka wykład

więcej podobnych podstron