Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3....

40

Transcript of Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3....

Page 1: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna
Page 2: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

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 HELIONul. Kościuszki 1c, 44-100 GLIWICEtel. 32 231 22 19, 32 230 98 63e-mail: [email protected]: 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/procloMoż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ść

Page 3: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Spis tre�ci

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

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

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

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

Rozdzia� 1. Wprowadzenie .........................................................................231.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 ..........................................................452.1. Konstrukcje sk�adniowe ......................................................................................46

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

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

2.4. Zmienne, wi�zania 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

Page 4: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

8 � Programowanie w j�zyku Clojure

Rozdzia� 3. Ujednolicanie danych za pomoc� sekwencji .......................813.1. Wszystko jest sekwencj� .....................................................................................83

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

3.3. Sekwencje niesko�czone 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 ...................................................1154.1. Zagadnienia z obszaru programowania funkcyjnego ...........................................116

4.2. Jak stosowa� „leniwe” podej�cie? ......................................................................121

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

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

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

Rozdzia� 5. Stan .........................................................................................1475.1. Wspó�bie�no��, równoleg�o�� 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. Zarz�dzanie stanem specyficznym dla w�tku za pomoc� zmiennych ....................163

5.6. Gra Snake w j�zyku Clojure .............................................................................168

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

Rozdzia� 6. Protoko�y i typy danych .......................................................1796.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

Page 5: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Spis tre�ci � 9

Rozdzia� 7. Makra .....................................................................................2017.1. Kiedy nale�y 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 ..........................................................................2258.1. ycie bez wielometod ......................................................................................226

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

8.3. Wi�cej ni� proste wybieranie metod ...................................................................231

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

8.5. Kiedy nale�y korzysta� z wielometod? ...............................................................237

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

Rozdzia� 9. Sztuczki z Jav� ......................................................................2439.1. Obs�uga wyj�tków ............................................................................................244

9.2. Zmagania z liczbami ca�kowitymi .....................................................................248

9.3. Optymalizowanie wydajno�ci ............................................................................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 ............................................................26910.1. Wynik w grze Clojurebreaker ..........................................................................270

10.2. Testowanie kodu zwracaj�cego 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

Page 6: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

22 � Programowanie w j�zyku Clojure

asedzielewski
Prostokąt
Page 7: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Rozdzia� 1.

Wprowadzenie

zybki wzrost popularno�ci 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�no�ci.

Wszystkie te cechy s� wa�ne, jednak �adna z nich nie odgrywa najwa�niejszej

roli. Naszym zdaniem najistotniejszymi aspektami j�zyka Clojure s� jego pro-

stota i mo�liwo�ci.

Prostota w kontek�cie oprogramowania jest wa�na z kilku wzgl�dów, tu jednak

mamy na my�li pierwotne i najwa�niejsze znaczenie tego s�owa — proste jest

to, co nie jest z�o�one. Proste komponenty umo�liwiaj� systemowi przeprowa-

dzanie operacji zaplanowanych przez projektantów i nie wykonuj� czynno�ci

niepowi�zanych z danym zadaniem. Z naszych do�wiadcze� wynika, �e nie-

wielka z�o�ono�� zwykle szybko przekszta�ca si� w niebezpiecznie powa�n�.

Tak�e s�owo mo�liwo�ci ma wiele znacze�. Tu mamy na my�li zdolno�� do

wykonywania stawianych aplikacji zada�. Aby programista mia� odpowiednie

mo�liwo�ci, musi wykorzysta� platform�, która sama je posiada i jest powszechnie

dost�pna. Tak� platform� jest na przyk�ad maszyna JVM. Ponadto u�ywane

narz�dzia musz� zapewnia� pe�ny, nieograniczony dost�p do oferowanych

mo�liwo�ci. Dost�p do mo�liwo�ci jest cz�sto podstawowym wymogiem w pro-

jektach, w których trzeba w pe�ni wykorzysta� platform�.

S

Page 8: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

24 � Programowanie w j�zyku Clojure

Przez lata tolerowali�my bardzo skomplikowane narz�dzia, które by�y jedynym

sposobem na uzyskanie potrzebnych mo�liwo�ci. Czasem akceptowali�my te� ogra-

niczone mo�liwo�ci w celu uproszczenia modelu programowania. Niekiedy nie da

si� unikn�� pewnych kompromisów, jednak w obszarze mo�liwo�ci i prostoty nie

trzeba si� z nimi godzi�. J�zyk Clojure to dowód na to, �e cechy te mo�na po��czy�.

1.1. Dlaczego Clojure?Wszystkie charakterystyczne cechy j�zyka Clojure maj� zapewnia� prostot�,

mo�liwo�ci lub i jedno, i drugie. Oto kilka przyk�adów:

� Programowanie funkcyjne jest proste, poniewa� pozwala oddzieli� ob-

liczenia od stanu i to�samo�ci. Zalet� jest to, �e programy funkcyjne s�

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

noleg�ego wykonywania.

� Konstrukcje umo�liwiaj�ce wspó�dzia�anie j�zyków Clojure i Java daj�

du�e mo�liwo�ci, poniewa� zapewniaj� bezpo�redni dost�p do sk�adni

Javy. Zalet� jest to, �e mo�na uzyska� wydajno�� na poziomie Javy

i stosowa� sk�adni� charakterystyczn� dla tego j�zyka. Co wa�niejsze,

nie trzeba ucieka� si� do j�zyka ni�szego poziomu, aby zapewni� sobie

dodatkowe mo�liwo�ci.

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

wczytywanie od wykonania, a jego sk�adnia obejmuje niewielk� liczb�

niezale�nych elementów. Zalet� jest to, �e wzorce projektowe s� uj�te

w abstrakcyjne konstrukcje sk�adniowe, a S-wyra�enia obejmuj� kod

w j�zykach XML, JSON i SQL.

� Lisp daje te� du�e mo�liwo�ci, poniewa� udost�pnia kompilator i sys-

tem makr dzia�aj�cy w czasie wykonywania programu. Zalet� jest to, �e

w Lispie wyst�puje póne wi�zanie i mo�na �atwo tworzy� j�zyki DSL.

� Model czasu w j�zyku Clojure jest prosty. Oddzielono w nim warto�ci,

to�samo��, stan i czas. Zalet� jest to, �e w programach mo�na spraw-

dza� i zapami�tywa� informacje bez obaw o to, �e starsze dane zostan�

nadpisane.

� Protoko�y s� proste. W Clojure polimorfizm jest niezale�ny od dzie-

dziczenia. Zalet� jest to, �e mo�na bezpiecznie i w konkretnym celu

rozszerza� 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).

Page 9: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Rozdzia� 1. • Wprowadzenie � 25

Ta lista cech stanowi „map�” pomocn� w dalszych rozdzia�ach ksi��ki. Nie

martw si�, je�li na razie nie rozumiesz wszystkich szczegó�ów. Ka�dej z tych

cech po�wi�camy ca�y 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� wi�ksze przyk�adowe programy, które prezentujemy dalej w ksi��ce.

J�zyk Clojure jest eleganckiW j�zyku Clojure stosunek sygna�u do szumu jest wysoki. Dlatego programy

pisane w tym j�zyku s� krótkie. Takie programy s� ta�sze w tworzeniu, insta-

lowaniu i konserwacji1. Jest to prawd� zw�aszcza wtedy, gdy programy s� zwi�-

z�e, a nie tylko tre�ciwe. 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 �a�cuch 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�-

puj� tu zmienne, modyfikowalny stan ani rozga��zienia. Efekt ten jest mo�liwy

dzi�ki funkcjom wy�szego rz�du. Funkcje tego rodzaju przyjmuj� inne funkcje

1 Software Estimation: Demystifying the Black Art [McC06] to znakomita ksi��ka.

Jej autorzy dowodz�, �e krótsze jest ta�sze.

Page 10: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

26 � Programowanie w j�zyku Clojure

jako argumenty i (lub) zwracaj� funkcje. Funkcja every? przyjmuje funkcj�

i kolekcj�, a zwraca warto�� true, je�li otrzymana funkcja zwraca true dla ka�-

dego elementu z kolekcji.

Poniewa� w wersji w j�zyku Clojure nie ma rozga��zie�, kod jest bardziej czy-

telny i �atwiejszy do przetestowania. Zalety te s� jeszcze wyraniejsze w wi�k-

szych programach. Ponadto, cho� kod jest zwi�z�y, mo�na go �atwo zrozumie�.

Program w j�zyku Clojure mo�na potraktowa� jak definicj� pustego �a�cucha

znaków — jest to �a�cuch, w którym ka�dy znak jest odst�pem. Kod ten jest

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

�a�cucha 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 zdefiniowa� w jednym wierszu:

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

Korzysta� z tego rekordu mo�na tak:

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

Page 11: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Rozdzia� 1. • Wprowadzenie � 27

Instrukcj� defrecord i powi�zane 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 s� z natury bezpieczne ze wzgl�du

na w�tki, a mechanizmy modyfikowania danych mo�na utworzy� w odr�bnej

warstwie za pomoc� referencji, agentów i atomów j�zyka Clojure. Techniki te

omawiamy w rozdziale 5., „Stan”. Poniewa� rekordy s� niezmienne, j�zyk

Clojure automatycznie udost�pnia poprawne implementacje funkcji hashCode()

i equals().

J�zyk Clojure ma wbudowanych wiele eleganckich rozwi�za�, je�li jednak

stwierdzisz, �e czego� Ci w nim brakuje, mo�esz samodzielnie doda� potrzebne

mechanizmy. Umo�liwiaj� to cechy Lispa.

Clojure to od�wie�ony LispClojure jest Lispem. Od dziesi�cioleci zwolennicy Lispa mówi� o przewagach,

jakie j�zyk ten ma w porównaniu z w�a�ciwie wszystkimi innymi j�zykami. Plan

opanowania �wiata przez Lispa jest jednak realizowany do�� powoli.

Twórcy j�zyka Clojure, podobnie jak autorzy ka�dej odmiany Lispa, musieli

zmierzy� si� z dwoma problemami. Oto one:

� Clojure ma odnie�� sukces jako odmiana Lispa. Wymaga to przeko-

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

nizmy swojego poprzednika.

� Jednocze�nie Clojure ma odnie�� sukces tam, gdzie wcze�niejsze wersje

Lispa si� nie przyj��y. Wymaga to zdobycia poparcia wi�kszej spo�ecz-

no�ci programistów.

Autorzy j�zyka Clojure radz� sobie z tymi problemami przez udost�pnienie me-

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

nie zestawu usprawnie� sk�adniowych u�atwiaj�cych stosowanie j�zyka Clojure

programistom, którzy nie znaj� Lispa.

Dlaczego Lisp?Wersje Lispa maj� ma�y rdze�, s� prawie pozbawione sk�adni i maj� rozbudo-

wane mechanizmy do obs�ugi makr. Z uwagi na te cechy mo�na zmodyfikowa�

Lispa pod k�tem projektu, zamiast dostosowywa� projekt do Lispa. Przyjrzyj si�

poni�szemu fragmentowi kodu w Javie:

Page 12: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

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 s� polimorficzne i mo�na je

dostosowa� do potrzeb. Jednak znaczenie ka�dego innego s�owa w przyk�ado-

wym kodzie jest okre�lane przez j�zyk. Czasem wygodna jest mo�liwo�� zmiany

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

� zdefiniowa� s�owo private jako „prywatne w kodzie produkcyjnym, ale

publiczne na potrzeby serializacji i testów jednostkowych”;

� zdefiniowa� s�owo class w taki sposób, aby platforma automatycznie

generowa�a metody pobieraj�ce i ustawiaj�ce dla pól prywatnych (o ile

programista nie zarz�dzi inaczej);

� utworzy� podklas� dla class i umie�ci� w niej wywo�ywane zwrotnie

uchwyty dla zdarze� cyklu �ycia; klasa z obs�ug� cyklu �ycia mo�e na

przyk�ad zg�asza� zdarzenie utworzenia egzemplarza tej klasy.

Natykali�my si� na programy, w których potrzebne by�y wszystkie te cechy. Bez

potrzebnych mechanizmów programi�ci musieli ucieka� si� do powtarzalnych

i podatnych na b��dy sztuczek. Aby poradzi� sobie z brakiem niezb�dnych

rozwi�za�, napisano dos�ownie miliony wierszy kodu.

W wi�kszo�ci j�zyków trzeba poprosi� osoby odpowiedzialne za implementacj�,

aby doda�y wspomniane wcze�niej mechanizmy. W Clojure mo�esz samodzielnie

doda� potrzebne cechy, pisz�c makra (rozdzia� 7., „Makra”). Nawet sam j�zyk

Clojure jest zbudowany za pomoc� makr, takich jak defrecord:

(defrecord name [arg1 arg2 arg3])

Je�li chcesz zmieni� znaczenie s�owa, mo�esz napisa� w�asne makro. Je�eli

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

czy pola nie maj� warto�ci null, wystarczy utworzy� w�asne makro defrecord.

Powinno ono wygl�da� tak:

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

Mo�liwo�� zmiany dzia�ania j�zyka w nim samym jest wyj�tkow� zalet� Lispa.

Mo�na znale� wiele opisów ró�nych aspektów tego podej�cia:

� Lisp jest homoikoniczny2. 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��

Page 13: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Rozdzia� 1. • Wprowadzenie � 29

� Ca�y j�zyk jest dost�pny w ka�dym momencie. Paul Graham w artykule

Revenge of the Nerds3 wyja�nia, dlaczego jest to wa�ne.

Sk�adnia Lispa eliminuje te� problemy z priorytetami operatorów i ��czno�ci�

operacji. W ksi��ce tej nie znajdziesz tabel dotycz�cych tych zagadnie�. Z uwagi

na wymóg stosowania nawiasów wyra�enia s� jednoznaczne.

Wad� prostej, jednolitej sk�adni Lispa (przynajmniej dla pocz�tkuj�cych) jest

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

st�pnia ciekawe po��czenie cech, które u�atwiaj� u�ywanie Lispa programistom

znaj�cym inne j�zyki.

Lisp z mniejsz� liczb� nawiasówClojure zapewnia istotne zalety programistom u�ywaj�cym innych odmian Lispa.

Oto te korzy�ci:

� W j�zyku Clojure fizyczne listy z Lispa s� uogólnione do abstrakcyjnej

postaci — sekwencji. Pozwala to zachowa� mo�liwo�ci, jakie daj� listy,

a przy tym wykorzysta� 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�liwo�ci Lispa!), jednak pod kilkoma wzgl�-

dami usprawniono tradycyjn� sk�adni� Lispa.

� Clojure zapewnia wygodn�, opart� 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�kszo�ci innych odmian Lispa. Mi�dzy

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 u�atwia czytanie definicji funkcji w j�zyku Clojure.

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

Page 14: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

30 � Programowanie w j�zyku Clojure

� W j�zyku Clojure, inaczej ni� w wi�kszo�ci odmian Lispa, przecinki

s� 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 warto�� 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 s� niepotrzebne.

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

Jest to kwestia czysto estetyczna i oba podej�cia maj� swoich zwolenników.

Wa�ne jest to, �e j�zyk Clojure pozbawiono uci��liwych aspektów Lispa,

je�li by�o to mo�liwe bez utraty zalet tego ostatniego.

Clojure jest �wietn� odmian� Lispa zarówno dla ekspertów, jak i dla pocz�t-

kuj�cych programistów Lispa.

Clojure to j�zyk funkcyjnyClojure jest j�zykiem funkcyjnym, natomiast nie jest (w odró�nieniu od Haskella)

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

� Funkcje to pe�noprawne obiekty. Oznacza to, �e funkcje mo�na two-

rzy� w czasie wykonywania programu, przekazywa�, zwraca� i ogólnie

u�ywa� 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 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")

Page 15: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Rozdzia� 1. • Wprowadzenie � 31

S�owo for nie jest pocz�tkiem p�tli, ale wyra�enia listowego (ang. list compre-

hension). Kod ten oznacza „dla ka�dego c z kolekcji compositions, gdzie nazw�

c jest "Requiem", podaj kompozytora c”. Wyra�enia listowe omawiamy w punkcie

„Przekszta�canie sekwencji”.

Przyk�adowy kod ma cztery po��dane 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ównoleg�ego wykonywania. Ka�dy krok mo�na przy-

dzieli� do odr�bnego w�tku bez konieczno�ci modyfikowania kodu po-

szczególnych kroków.

� Jest uniwersalny. Kolekcj� compositions mo�e by� zwyk�y 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. Wi�kszo�� programów obiektowych pisze si�

w stylu imperatywnym, dlatego nie maj� one �adnych z wymienionych wcze�niej

zalet. S� niepotrzebnie skomplikowane, niebezpieczne ze wzgl�du na w�tki, nie

umo�liwiaj� równoleg�ego dzia�ania, a kod jest trudny do uogólnienia. Bezpo-

�rednie porównanie podej�cia funkcyjnego i imperatywnego znajdziesz w pod-

rozdziale 2.7, „Gdzie si� podzia�a p�tla for?”.

Programi�ci znaj� zalety j�zyków funkcyjnych ju� od d�ugiego czasu. Jednak

j�zyki funkcyjne, na przyk�ad Haskell, nie zdoby�y dominuj�cej pozycji. Wyni-

ka to z tego, �e nie wszystkie operacje mo�na wygodnie wykona� w podej�ciu

czysto funkcyjnym.

S� cztery powody, dla których j�zyk Clojure mo�e zyska� wi�ksze zaintereso-

wanie ni� dawne j�zyki funkcyjne:

� Podej�cie funkcyjne jest dzi� bardziej przydatne ni� kiedykolwiek

wcze�niej. Pojawiaj� si� maszyny o coraz wi�kszej liczbie rdzeni, a j�-

zyki funkcyjne pozwalaj� �atwo wykorzysta� mo�liwo�ci takiego sprz�tu.

Programowanie funkcyjne omawiamy w rozdziale 4., „Programowanie

funkcyjne”.

� W j�zykach funkcyjnych niewygodnie zarz�dza si� stanem, je�li musi

si� on zmienia�. Clojure udost�pnia mechanizmy do obs�ugi zmien-

nego stanu za pomoc� programowej pami�ci transakcyjnej i referencji,

agentów, atomów i wi�zania dynamicznego.

Page 16: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

32 � Programowanie w j�zyku Clojure

� W wielu j�zykach funkcyjnych typy s� okre�lane statycznie. W j�zyku

Clojure stosuje si� dynamiczne okre�lanie typów, co u�atwia zadanie

programistom poznaj�cym dopiero programowanie funkcyjne.

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

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

nych obiektów. Zapewnia to wygod� pocz�tkuj�cym, którzy ucz� si�

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

gnowa� z podej�cia funkcyjnego. Wywo�ywanie kodu Javy opisujemy

w rozdziale 9., „Sztuczki z Jav�”.

Mechanizmy zarz�dzania zmian� stanu w j�zyku Clojure umo�liwiaj� pisanie

programów wspó�bie�nych bez bezpo�redniego korzystania z blokad i uzupe�-

niaj� podstawowy funkcjonalny rdze� j�zyka.

Clojure upraszcza programowanie wspó�bie�neMechanizmy programowania funkcyjnego dost�pne w Clojure u�atwiaj� pisanie

kodu bezpiecznego ze wzgl�du na w�tki. Poniewa� niezmienne struktury danych

nigdy si� nie zmieniaj�, nie wyst�puje zagro�enie uszkodzeniem danych w wy-

niku dzia�ania innych w�tków.

Jednak obs�uga wspó�bie�no�ci w Clojure wykracza poza mechanizmy progra-

mowania funkcyjnego. Je�li potrzebne s� referencje do zmiennych danych, Clojure

zabezpiecza je za pomoc� programowej pami�ci transakcyjnej (ang. software

transactional memory — STM). STM s�u�y do tworzenia kodu bezpiecznego

ze wzgl�du na w�tki i jest rozwi�zaniem wy�szego poziomu ni� blokady z Javy.

Zamiast stosowa� podatne na b��dy strategie blokowania danych, mo�na za-

bezpieczy� wspó�u�ytkowany stan za pomoc� transakcji. Jest to du�o lepsze

podej�cie, poniewa� wielu programistów dobrze zna transakcje z uwagi na do-

�wiadczenie w korzystaniu z baz danych.

Poni�szy kod tworzy dzia�aj�c�, bezpieczn� ze wzgl�du na w�tki baz� danych

z kontami przechowywan� w pami�ci:

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

Funkcja ref tworzy zabezpieczon� za pomoc� transakcji referencj� do bie��cego

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

zujemy, jak doda� do bazy nowe konto:

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

Page 17: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Rozdzia� 1. • Wprowadzenie � 33

Instrukcja dosync powoduje aktualizowanie bazy accounts w transakcji. Rozwi�-

zanie to zapewnia bezpiecze�stwo ze wzgl�du na w�tki i jest �atwiejsze w sto-

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

obiekty i w jakiej kolejno�ci nale�y zablokowa�. Podej�cie transakcyjne spraw-

dza si� lepiej tak�e w niektórych standardowych zastosowaniach. Przyk�adowo:

w modelu tym w�tki wczytuj�ce dane nigdy nie musz� blokowa� danych.

Cho� przedstawiony przyk�ad jest bardzo prosty, technika jest ogólna i spraw-

dza si� tak�e w praktyce. Wi�cej informacji o wspó�bie�no�ci i pami�ci STM

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

Wykorzystanie maszyny JVM w ClojureClojure zapewnia przejrzysty, prosty i bezpo�redni dost�p do Javy. W kodzie

mo�na bezpo�rednio wywo�a� 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 wspomnie�, �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

obejmuj� implementacj� interfejsów Callable i Runnable. Dlatego mo�na �atwo

przekaza� poni�sz� funkcj� anonimow� do konstruktora klasy Thread Javy:

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

Dziwne dane wyj�ciowe wynikaj� ze sposobu wy�wietlania 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 w�tek dzia�a a� do zako�czenia pracy,

natomiast jego dane wyj�ciowe mog� w dziwny sposób przeplata� si� z wierszami

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

wynik zapisywania danych do strumienia wyj�cia przez wi�cej ni� jeden w�tek).

Page 18: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

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 bezpo�rednio, zamiast ukrywa� kod w tym j�zyku za

charakterystycznymi dla Lispa nak�adkami.

Pozna�e� ju� kilka powodów do stosowania j�zyka Clojure. Pora przyst�pi� do

pisania kodu.

1.2. Szybkie wprowadzeniedo programowania w Clojure

Aby uruchomi� �rodowisko j�zyka Clojure i kod z tej ksi��ki, potrzebujesz

dwóch rzeczy. Oto one:

� �rodowisko uruchomieniowe Javy. Pobierz4 i zainstaluj Jav� w wersji

5. lub nowszej. W wersji 6. znacznie poprawiono wydajno�� i system

informowania o wyj�tkach, dlatego warto stosowa� w�a�nie j�.

� Leiningen5. Leiningen to narz�dzie do zarz�dzania zale�no�ciami i uru-

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

j�zyka Clojure narz�dzie do wykonywania tych zada�.

Leiningen pos�u�y do zainstalowania j�zyka Clojure i wszystkich elementów

wymaganych w przyk�adowym kodzie. Je�li masz ju� zainstalowane narz�dzie

Leiningen, wiesz zapewne, jak z niego korzysta�. Je�eli jeszcze nie masz po-

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

w serwisie GitHub6. Znajdziesz tam instrukcje dotycz�ce instalacji, a tak�e pod-

stawowe informacje na temat u�ytkowania Leiningena. Nie musisz jednak uczy�

si� wszystkiego, poniewa� w ksi��ce opisujemy polecenia potrzebne do uru-

chomienia przyk�adów.

W trakcie pracy z ksi��k� korzystaj z j�zyka Clojure w wersji w�a�ciwej dla

przyk�adowego kodu. Po przeczytaniu ksi��ki mo�esz zastosowa� si� do in-

strukcji z ramki „Samodzielne budowanie j�zyka Clojure” i zbudowa� aktualn�

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

Page 19: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Rozdzia� 1. • Wprowadzenie � 35

W punkcie „Pobieranie przyk�adowego kodu”, znajdziesz instrukcje dotycz�ce

pobierania przyk�adowego kodu. Po �ci�gni�ciu przyk�adowego kodu trzeba

u�y� Leiningena do pobrania zale�no�ci. W katalogu g�ównym z kodem wywo�aj

nast�puj�c� instrukcj�:

lein deps

Samodzielne budowanie j�zyka Clojure

Mo�liwe, �e chcesz zbudowa� j�zyk Clojure na podstawie kodu �ród�o-wego, aby uzyska� nowe funkcje i wprowadzi� poprawki b��dów. Mo�nazrobi� to w nast�puj�cy sposób:

git clone git://github.com/clojure/clojure.gitcd clojuremvn package

Przyk�adowy kod jest regularnie aktualizowany pod k�tem nowych rozwi�-za� wprowadzanych w j�zyku Clojure. Zapoznaj si� z plikiem README

w przyk�adowym kodzie, aby sprawdzi� numer najnowszej wersji, dlaktórej sprawdzono kod.

Zale�no�ci s� pobierane i umieszczane w odpowiednim miejscu. Mo�esz prze-

testowa� zainstalowane narz�dzia przez przej�cie do katalogu z przyk�adowym

kodem i uruchomienie �rodowiska REPL j�zyka Clojure. Leiningen obejmuje

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

z zale�no�ciami potrzebnymi w dalszych rozdzia�ach.

lein repl

Po udanym uruchomieniu �rodowiska REPL powinien pojawi� si� wiersz

zach�ty z tekstem user=>:

Clojureuser=>

Teraz jeste� gotowy do wy�wietlenia tekstu „Witaj, �wiecie”.

Korzystanie ze �rodowiska REPLAby pokaza�, jak korzysta� ze �rodowiska REPL, tworzymy kilka wersji kodu

wy�wietlaj�cego tekst „Witaj, �wiecie”. Najpierw wpisz kod (println "Witaj,

�wiecie") w wierszu zach�ty �rodowiska REPL.

user=> (println "Witaj, �wiecie")

-> Witaj, �wiecie

Page 20: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

36 � Programowanie w j�zyku Clojure

Drugi wiersz, Witaj, �wiecie, to ��dane dane wyj�ciowe z konsoli.

Teraz umie��my kod w funkcji, która potrafi „zwraca� 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 ��cz�cej dowoln� list� argumentów w �a�cuch

znaków;

� defn, hello, name i str to symbole, czyli nazwy prowadz�ce do ró�nych

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

Przyjrzyj si� zwracanej warto�ci, #'user/hello. Przedrostek #' oznacza, �e

funkcj� zapisano w zmiennej j�zyka Clojure, a user to przestrze nazw, w której

znajduje si� ta funkcja. Jest to domy�lna przestrze� nazw w �rodowisku REPL,

odpowiadaj�ca domy�lnemu 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 mo�na wywo�a� funkcj� hello i przekaza� do niej imi�.

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

Je�li �rodowisko REPL znajduje si� w dziwnym stanie, naj�atwiej zamkn�� je

za pomoc� kombinacji klawiszy Ctrl+C w systemie Windows lub Ctrl+D

w systemach uniksowych, a nast�pnie ponownie uruchomi�.

Specjalne zmienne�rodowisko REPL obejmuje szereg przydatnych zmiennych specjalnych. W czasie

pracy w �rodowisku REPL wyniki obliczania trzech ostatnich wyra�e� znaj-

duj� si� w specjalnych zmiennych *1, *2 i *3. Pozwala to na wygodn� prac�

w modelu iteracyjnym. Spróbujmy po��czy� kilka powita�.

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

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

Page 21: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Rozdzia� 1. • Wprowadzenie � 37

Teraz mo�na zastosowa� specjalne zmienne do po��czenia wyników ostatnich

instrukcji.

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

Pope�nienie b��du w �rodowisku REPL prowadzi do zg�oszenia wyj�tku Javy

(z uwagi na zwi�z�o�� 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�a�. W specjalnej zmiennej *e znajduj�

si� informacje o ostatnim wyj�tku. Poniewa� wyj�tki w Clojure s� wyj�tkami

Javy, mo�na wy�wietli� stos wywo�a� za pomoc� instrukcji pst (od ang. print

stacktrace, czyli wy�wietl stos wywo�a�)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 Jav� omawiamy w rozdziale 9., „Sztuczki z Jav�”.

Je�li blok kodu jest zbyt d�ugi, aby mo�na go wygodnie wpisa� w �rodowisku

REPL, umie�� kod w pliku, a nast�pnie wczytaj ten plik w �rodowisku. Mo�esz

u�y� �cie�ki bezwzgl�dnej lub poda� j� wzgl�dem miejsca uruchomienia �rodo-

wiska REPL.

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

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

natychmiastowych informacji zwrotnych. Aby jak najlepiej wykorzysta� ksi��k�,

w trakcie jej lektury nie zamykaj �rodowiska REPL.

7 Instrukcja pst jest dost�pna tylko w Clojure 1.3.0 i nowszych wersjach.

Page 22: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

38 � Programowanie w j�zyku Clojure

Dodawanie stanu wspó�u�ytkowanegoFunkcja 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.

S� tak�e �atwe do zrozumienia, dlatego w wielu sytuacjach warto je stosowa�.

Jednak w wi�kszo�ci programów wyst�puje wspó�u�ytkowany stan, a do zarz�-

dzania nim s�u�� funkcje typu impure (czyli takie, które nie s� czyste). Dodajmy

do funkcji hello mechanizm �ledzenia liczby u�ytkowników. Najpierw trzeba

utworzy� struktur� danych do przechowywania tej liczby. U�yjmy do tego zbioru.

#{}-> #{}

#{} to litera� oznaczaj�cy pusty zbiór. Potrzebna jest te� operacja conj.

(conj coll item)

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

elementem. Do��czmy element do zbioru, aby upewni� si�, �e powstaje nowy zbiór.

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

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

dzanie aktualnego zbioru u�ytkowników. Clojure udost�pnia kilka s�u��cych do

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

(atom initial-state)

Aby okre�li� nazw� atomu, nale�y u�y� instrukcji def.

(def symbol initial-value?)

Instrukcja def przypomina polecenie defn, ale jest ogólniejsza. Przy jej u�yciu

mo�na definiowa� funkcje lub dane. U�yjmy s�owa atom do utworzenia atomu

i instrukcji def do powi�zania atomu z nazw� visitors.

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

Aby zaktualizowa� referencj�, trzeba u�y� 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 wstawi� u�ytkow-

nika do kolekcji visitors, u�ywaj�c do aktualizowania funkcji conj.

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

Page 23: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

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 sprawdzi� zawarto�� 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 zbudowa� now�, bardziej rozbudowan� wersj� funkcji hello.

src/examples/introduction.clj

(defn hello "Wy�wietla powitanie na wyj�ciu, u�ywaj�c nazwy u�ytkownika.

Potrafi stwierdzi�, �e korzysta�e� ju� z programu." [username] (swap! visitors conj username) (str "Witaj, " username))

Teraz sprawdmy, czy u�ytkownicy s� 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�a�nie polega problem ze stanem. Efekty s� ró�ne w zale�no�ci od tego, kiedy

zasz�y dane zdarzenia. Zrozumie� funkcj� mo�na na podstawie jej analizy.

Aby zrozumie� stan, trzeba pozna� ca�� histori� dzia�ania programu.

Je�li to mo�liwe, unikaj przechowywania stanu. Je�eli jest to niemo�liwe, dbaj

o to, aby stanem mo�na by�o zarz�dza�. U�ywaj do tego typów referencyjnych,

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

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

nienie bezpiecze�stwa nie wymaga stosowania blokad, które bywaj� skompli-

kowane w u�yciu.

Na tym etapie powiniene� umie� ju� wprowadza� krótkie fragmenty kodu

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

nie. Tak�e biblioteki j�zyka Clojure mo�na wczytywa� i uruchamia� z poziomu

�rodowiska REPL. Dalej pokazujemy, jak to zrobi�.

Page 24: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

40 � Programowanie w j�zyku Clojure

1.3. Biblioteki j�zyka ClojureKod 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 wczyta� za pomoc� instrukcji require.

(require quoted-namespace-symbol)

Je�li programista ��da biblioteki o nazwie clojure.java.io, Clojure szuka pliku

o nazwie clojure/java/io.clj w �cie�ce ze zmiennej CLASSPATH. Zobaczmy, jaki jest

tego efekt.

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

Pocz�tkowy pojedynczy apostrof (') jest niezb�dny i s�u�y do dos�ownego 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 mo�esz wczyta� 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,

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

„»Leniwe« podej�cie”. Na razie upewnij si�, �e mo�esz uruchomi� przyk�adow�

funkcj� fibs. Wprowad poni�szy 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)

Je�li otrzyma�e� 10 pierwszych liczb Fibonacciego (wymienionych powy�ej),

poprawnie zainstalowa�e� przyk�adowy kod z ksi��ki.

Wszystkie przyk�ady sprawdzili�my za pomoc� testów jednostkowych (testy

znajduj� si� w katalogu examples/test). Samych testów nie omawiamy w ksi��ce,

jednak mog� okaza� si� przydatnym ród�em wiedzy. Aby uruchomi� testy jed-

nostkowe, u�yj instrukcji lein test.

Page 25: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Rozdzia� 1. • Wprowadzenie � 41

Instrukcje require i usePo za��daniu biblioteki j�zyka Clojure za pomoc� instrukcji require elementy

z biblioteki trzeba wskazywa� za pomoc� pe�nej nazwy. Zamiast nazwy fibs

trzeba u�y� okre�lenia examples.introduction/fibs. Uruchom drugi egzemplarz

�rodowiska REPL8 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�y� instrukcji

refer dla przestrzeni nazw i odwzorowa� wszystkie nazwy z tej przestrzeni na

bie��c� przestrze� nazw.

(refer quoted-namespace-symbol)

Wywo�aj instrukcj� refer dla przestrzeni examples.introduction i sprawd, czy

mo�esz bezpo�rednio wywo�a� 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 nast�puj�ce 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 ksi��ki mo�esz wywo�a� instrukcj�

require lub use z opcj� :reload, aby wymusi� ponowne wczytanie biblioteki.

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

Opcja :reload jest przydatna, je�li wprowadzasz zmiany i chcesz sprawdzi� ich

efekt bez ponownego uruchamiania �rodowiska REPL.

8 Otwarcie nowego �rodowiska REPL zapobiega konfliktom nazw mi�dzy utworzonym

wcze�niej kodem a funkcjami o tych samych nazwach z przyk�adowego kodu. W praktyce

nie stanowi to problemu. Zagadnienie to omawiamy w punkcie „Przestrzenie nazw”.

Page 26: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

42 � Programowanie w j�zyku Clojure

Znajdowanie dokumentacjiPotrzebna dokumentacja cz�sto jest dost�pna bezpo�rednio w �rodowisku REPL.Najprostsz� funkcj� pomocnicz�

9 jest doc.

(doc name)

U�yjmy funkcji doc do wy�wietlenia dokumentacji funkcji str.

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

Pierwszy wiersz danych wyj�ciowych funkcji doc obejmuje pe�n� nazw� spraw-dzanej funkcji. W drugim znajduj� si� argumenty generowane bezpo�redniow kodzie. Wybrane cz�sto stosowane nazwy argumentów i ich zastosowanieomawiamy w ramce „Zwyczajowe nazwy parametrów”. Dalsze wiersze obejmuj��acuch znaków dokumentacji, je�li jest on podany w definicji funkcji.

Zwyczajowe nazwy parametrówa�cuchy znaków dokumentacji w funkcjach reduce i areduce obejmuj�szereg krótkich nazw parametrów. Oto niektórych z tych nazw i sposobyich stosowania.

Parametr Zastosowaniea Tablica Javyagt Agentcoll Kolekcjaexpr Wyra�enief Funkcjaidx Indeksr Referencjav Wektorval Warto�

Nazwy mog� wydawa� si� krótkie, jednak jest tak nie bez powodu —„dobre” nazwy cz�sto s� ju� „zaj�te” przez funkcje j�zyka Clojure! U�y-wanie dla parametrów nazw identycznych z nazwami funkcji jest dopusz-czalne, ale uznaje si� to za oznak� z�ego stylu. Parametr zas�ania wtedyfunkcj�, dlatego jest ona niedost�pna, kiedy parametr znajduje si� w za-si�gu programu. Dlatego nie nale�y nazywa� referencji ref, agentówagent, a liczników — count, poniewa� s� to nazwy funkcji.

9 Tak naprawd� doc to makro j�zyka Clojure.

Page 27: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Rozdzia� 1. • Wprowadzenie � 43

�a�cuch znaków dokumentacji mo�na doda� do funkcji przez umieszczenie go

bezpo�rednio 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-

�ciowe funkcji doc pasuj� do przekazanego wyra�enia regularnego lub �a�cucha

znaków.

(find-doc s)

Za pomoc� funkcji find-doc mo�na sprawdzi�, w jaki sposób Clojure skraca

kolekcje.

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

Funkcja reduce pozwala w skrócony sposób stosowa� operacje do kolekcji

j�zyka Clojure. Omawiamy j� w punkcie „Przekszta�canie sekwencji”. Funkcja

areduce wspó�dzia�a z tablicami Javy, a opisujemy j� w punkcie „Korzystanie

z kolekcji Javy”.

Du�a cz��� j�zyka Clojure jest napisana w nim samym, dlatego lektura jego

kodu ród�owego to pouczaj�ce zadanie. Kod ród�owy funkcji j�zyka Clojure

mo�na wy�wietli� za pomoc� instrukcji source z biblioteki repl.

(clojure.repl/source symbol)

Wy�wietlmy kod ród�owy prostej funkcji identity.

(use 'clojure.repl)(source identity)

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

Page 28: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

44 � Programowanie w j�zyku Clojure

Oczywi�cie, mo�na te� u�ywa� interfejsu API Reflection Javy. Metody class,

ancestors, instance? i podobne pozwalaj� sprawdzi� model obiektowy Javy

i informuj� na przyk�ad o tym, �e kolekcje j�zyka Clojure s� jednocze�nie 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 j�zyka Clojure znajdziesz na stronie

http://clojure.github.com/clojure. W ramce widocznej w prawej cz��ci tej strony

znajduj� si� odno�niki do wszystkich funkcji i makr. Po lewej stronie umiesz-

czono odno�niki do artyku�ów na temat ró�nych cech j�zyka Clojure.

1.4. PodsumowanieW�a�nie zako�czy�e� szybki przegl�d j�zyka Clojure. Pozna�e� daj�c� du�e

mo�liwo�ci sk�adni� tego j�zyka i jego zwi�zki z Lispem, a tak�e zobaczy�e�, jak

�atwe jest wywo�ywanie w Clojure kodu Javy.

Uruchomi�e� j�zyk Clojure w swoim �rodowisku, a tak�e napisa�e� w �rodowisku

REPL krótkie programy ilustruj�ce programowanie funkcyjne i s�u��cy do obs�ugi

stanu model referencji. Pora przyjrze� si� ca�emu j�zykowi.

Page 29: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Skorowidz

Aagenty, 158

bie��ca warto��, 159

sprawdzanie poprawno�ci, 160

transakcje, 161

tworzenie, 158

wykrywanie b��dów, 160

algebra relacji, 110

Apache Ant, 244

atomy, 157

dereferencja, 157

tworzenie, 157

ustawienie warto�ci, 157

Bbiblioteki, 20, 40

dos�owne podawanie nazwy, 40

drzewo w�a�ciwo�ci systemowych, 238

znajdowanie dokumentacji, 42

CClojure, 15, 23

aktualizacja, 261

aspekty, 23

biblioteki, 20, 40

drzewo w�a�ciwo�ci 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�a� zwrotnych, 256

parsery SAX, 255

�rodowisko uruchomieniowe, 34

tworzenie klas, 255

Page 30: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

302 � Programowanie w j�zyku Clojure

Clojure

Java

tworzenie po�redników, 255

tworzenie tablic, 258

wykorzystanie mo�liwo�ci, 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 wyj�tków, 244

kontrolowane wyj�tki, 245

porz�dkowanie zasobów, 245

reagowanie na wyj�tki, 247

optymalizowanie wydajno�ci, 250

dodawanie sugestii typów, 253

u�ywanie typów prostych, 250

pobieranie zale�no�ci, 261

po��czenie z witryn�, 261

programowanie, 16

funkcyjne, 18, 24, 115

p�tle, 74

regu�y, 120

wspó�bie�ne, 32

protoko�y, 24, 179, 184

przestrze� nazw, 36, 61, 65

rejestrowanie informacji, 264

rekordy, 193

rozk�adanie struktury, 63

mo�liwo�ci, 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

�rodowisko REPL, 35

zmienne specjalne, 36

to�samo��, 147

typy referencyjne, 147

tworzenie aplikacji, 269

gra Clojurebreaker, 270

typy danych, 179, 188

cechy, 188

typy referencyjne, 38

atom, 38

warto��, 147

wi�zania, 61

wielometody, 225

wspó�bie�no��, 18, 32, 148

powody stosowania, 148

sytuacja wy�cigu, 149

zakleszczenie, 149

zmienne, 36, 61

cechy, 62

Ddefinicja pustego �a�cucha znaków, 26

duck typing, 250

Ffunkcje, 56

anonimowe, 58

konstrukcja, 59

powody tworzenia, 58

stosowanie, 61

unikanie, 223

Page 31: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Skorowidz � 303

bez sprawdzania przepe�nienia, 251

cz��ciowe 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

�a�cuchy 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

wi�zania, 62

zasi�g leksykalny, 63

wywo�anie, 47, 56

notacja przedrostkowa, 47

notacja wrostkowa, 47

zbiory, 109

z�o�one, 134

Hhermetyzacja, 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

Iinstrukcje

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

Page 32: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

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

JJava, 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 wyj�tków, 244

kontrolowane wyj�tki, 244

porz�dkowanie zasobów, 245

sekwencje, 98

kolekcje sekwencyjne, 98

wywo�ywanie kodu, 68

Kkod 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

wy�wietlanie w��a i jab�ka, 175

model funkcyjny, 169

add-points, 170, 171

assoc, 171

cons, 171

dodawanie punktów, 170

eats?, 172

Page 33: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

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

�a�cuch 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

warto�� logiczna, 46

regu�y dzia�ania, 51

warto�� nil, 46

wektory, 46

sekwencje, 84

zbiory, 46

sekwencje, 85

znak, 46

LLeiningen, 34, 261

pobieranie zale�no�ci, 35

wtyczka lein-noir, 287

leniwe sekwencje, 121, 125

moment realizacji, 127

Lisp, 15, 24

Mmakra, 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

Page 34: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

306 � Programowanie w j�zyku Clojure

makra

konstrukcje specjalne, 215

lazy-seq, 125

let, 221

letfn, 124

manipulowanie list�, 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

warto�ciowanie 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 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 wyra�enia regularnego, 56

maszyny JVM, 15, 29

autorekurencja, 124

Clojure, 16

Java, 16

memoizacja, 165

metadane, 77

standardowe klucze, 78

model czasu, 24

Nniezmienne struktury danych, 27

Ooptymalizacja TCO, 73, 123

Ppami�� 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 podej�cie, 118, 121

leniwe sekwencje, 121, 125

problemy rekurencyjne, 138

prosta rekurencja, 122

Page 35: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

Skorowidz � 307

regu�y, 120

rekurencja, 118

rekurencja ko�cowa, 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 poprawno�ci,

280

przeprowadzanie testów, 276, 283

sprawdzanie poprawno�ci danych

wyj�ciowych, 277

sprawdzanie poprawno�ci kodu, 278

TDD, 286

testy jednostkowe, 286

testy regresji, 277

tworzenie danych wej�ciowych, 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

przestrze� nazw, 36, 65

clojure.core, 66

clojure.string, 67

funkcje, 68

modyfikacja deklaracji, 264

myapp, 66

user, 36, 65

wi�zania, 65

Rreferencje, 150

sprawdzanie poprawno�ci, 156

transakcje, 150

ACID, 151

aktualizowanie informacji, 152

atomowe, 151

izolowane, 151

licznik, 155

pami�� STM, 151

skoordynowane, 151

spójne, 151

trwa�e, 151

warto�� wewn�trztransakcyjna, 153

w�a�ciwo�ci, 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 ko�cowa, 123

optymalizacja TCO, 123

rekurencja wzajemna, 136

memoizacja, 144

optymalizowanie, 139

przekszta�canie na autorekurencj�, 138

zast�powanie leniwym podej�ciem, 141

Page 36: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

308 � Programowanie w j�zyku Clojure

Ssekwencje, 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��ca warto��, 159

sprawdzanie poprawno�ci, 160

transakcje, 161

tworzenie, 158

wykrywanie b��dów, 160

atomy, 147, 157

dereferencja, 157

tworzenie, 157

ustawienie warto�ci, 157

model aktualizacji, 163

modele zarz�dzania, 168

referencje, 147, 150

transakcje, 150

tworzenie, 150

wywo�ywane zwrotnie metody, 166

zmienne, 147, 163

��rodowisko REPL, 35

zmienne specjalne, 36

Ttworzenie 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 poprawno�ci,

280

random-secret, 280

require, 279

score print-table, 276

score-inputs, 278

selections, 275

sprawdzanie poprawno�ci danych

wyj�ciowych, 277

test dla danych wej�ciowych, 276

test-dirs, 283

test-namespaces, 283

test-vars, 283

testy regresji, 277

tworzenie danych wej�ciowych, 275

zg�aszanie b��du, 284

tworzenie interfejsu, 287

board, 290

defpartial, 288

dodanie stanu, 287

Page 37: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

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

Wwi�zania, 62

bindings, 63

dynamiczne, 164

modyfikacje na odleg�o��, 164

dynamicznie okre�lany zasi�g, 164

funkcje, 62

zasi�g leksykalny, 63

lokalne, 164

mechanizm rozk�adania struktury, 63

podstawowe, 61

przestrze� nazw, 65

zmienne, 62

wielometody, 225

account-level, 235

assert-expr, 240

definiowanie, 228

dodawanie implementacji metod, 228

domy�lne dzia�anie, 230

dorane 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

rozwi�zywanie konfliktów, 232

wspó�bie�no��, 32

wyra�enie listowe, 94

elementy, 94

Zzmienne, 36, 61, 163

aliasy, 62

cechy, 62

mechanizm rozk�adania struktury, 63

metadane, 62

rodzaje definicji, 133

specjalne, 164

modyfikacje na odleg�o��, 164

tworzenie, 133

makra, 218

wi�zania, 62

lokalne dla w�tku, 164

podstawowe, 61

Page 38: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna

310 � Programowanie w j�zyku Clojure

Page 40: Tytuł oryginału: Programming Clojure€¦ · 8 Programowanie w jzyku Clojure Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .....81 3.1. Wszystko ... W Clojure Java jest sekwencyjna