Page 1


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ść


Spis treci

Podzikowania ............................................................................................10 Przedmowa do wydania drugiego .............................................................11 Przedmowa do wydania pierwszego ........................................................13 Wstp ...........................................................................................................15 Rozdzia 1. Wprowadzenie .........................................................................23 1.1. Dlaczego Clojure? .............................................................................................24 1.2. Szybkie wprowadzenie do programowania w Clojure ...........................................34 1.3. Biblioteki jzyka Clojure .....................................................................................40 1.4. Podsumowanie ..................................................................................................44 Rozdzia 2. Przegld jzyka Clojure ..........................................................45 2.1. Konstrukcje skadniowe ......................................................................................46 2.2. Makra odczytu ...................................................................................................55 2.3. Funkcje .............................................................................................................56 2.4. Zmienne, wizania i przestrzenie nazw ...............................................................61 2.5. Wywoywanie kodu Javy .....................................................................................68 2.6. Przepyw sterowania ..........................................................................................70 2.7. Gdzie si podziaa ptla for? ..............................................................................74 2.8. Metadane ..........................................................................................................77 2.9. Podsumowanie ..................................................................................................79

Kup książkę

Poleć książkę


8



Programowanie w jzyku Clojure

Rozdzia 3. Ujednolicanie danych za pomoc sekwencji .......................81 3.1. Wszystko jest sekwencj .....................................................................................83 3.2. Stosowanie biblioteki sekwencji ...........................................................................87 3.3. Sekwencje nieskoczone i „leniwe” .....................................................................96 3.4. W Clojure Java jest sekwencyjna .........................................................................98 3.5. Funkcje przeznaczone dla konkretnych struktur ..................................................104 3.6. Podsumowanie ................................................................................................113 Rozdzia 4. Programowanie funkcyjne ...................................................115 4.1. Zagadnienia z obszaru programowania funkcyjnego ...........................................116 4.2. Jak stosowa „leniwe” podejcie? ......................................................................121 4.3. Leniwsze ni leniwe .........................................................................................130 4.4. Jeszcze o rekurencji ..........................................................................................136 4.5. Podsumowanie ................................................................................................146 Rozdzia 5. Stan .........................................................................................147 5.1. Wspóbieno, równolego i blokady .............................................................148 5.2. Referencje i pami STM ................................................................................150 5.3. Nieskoordynowane i synchroniczne aktualizacje za pomoc atomów ....................157 5.4. Stosowanie agentów do asynchronicznego aktualizowania danych .......................158 5.5. Zarzdzanie stanem specyficznym dla wtku za pomoc zmiennych ....................163 5.6. Gra Snake w jzyku Clojure .............................................................................168 5.7. Podsumowanie ................................................................................................178 Rozdzia 6. Protokoy i typy danych .......................................................179 6.1. Programowanie z wykorzystaniem abstrakcji ......................................................180 6.2. Interfejsy .........................................................................................................183 6.3. Protokoy ........................................................................................................184 6.4. Typy danych ...................................................................................................188 6.5. Rekordy ..........................................................................................................193 6.6. Makro reify .....................................................................................................198 6.7. Podsumowanie ................................................................................................199

Kup książkę

Poleć książkę


Spis treci



9

Rozdzia 7. Makra .....................................................................................201 7.1. Kiedy naley stosowa makra? ..........................................................................202 7.2. Makro do sterowania przebiegiem programu ......................................................202 7.3. Upraszczanie makr ..........................................................................................209 7.4. Taksonomia makr ............................................................................................214 7.5. Podsumowanie ................................................................................................224 Rozdzia 8. Wielometody ..........................................................................225 8.1. ycie bez wielometod ......................................................................................226 8.2. Definiowanie wielometod .................................................................................228 8.3. Wicej ni proste wybieranie metod ...................................................................231 8.4. Tworzenie dora nych taksonomii ......................................................................233 8.5. Kiedy naley korzysta z wielometod? ...............................................................237 8.6. Podsumowanie ................................................................................................241 Rozdzia 9. Sztuczki z Jav ......................................................................243 9.1. Obsuga wyjtków ............................................................................................244 9.2. Zmagania z liczbami cakowitymi .....................................................................248 9.3. Optymalizowanie wydajnoci ............................................................................250 9.4. Tworzenie klas Javy w jzyku Clojure ................................................................255 9.5. Praktyczny przykad .........................................................................................261 9.6. Podsumowanie ................................................................................................268 Rozdzia 10. Tworzenie aplikacji ............................................................269 10.1. Wynik w grze Clojurebreaker ..........................................................................270 10.2. Testowanie kodu zwracajcego wynik ..............................................................274 10.3. Biblioteka test.generative ................................................................................278 10.4. Tworzenie interfejsu .......................................................................................287 10.5. Instalowanie kodu ..........................................................................................292 10.6. Poegnanie ....................................................................................................295 Dodatek A. Edytory kodu .........................................................................297 Dodatek B. Bibliografia ............................................................................299 Skorowidz ..................................................................................................301

Kup książkę

Poleć książkę


22



Kup książkę

Programowanie w jzyku Clojure

Poleć książkę


Rozdzia 1.

Wprowadzenie

S

zybki wzrost popularnoci jzyka Clojure wynika z wielu przyczyn. Po krótkich poszukiwaniach w sieci WWW dowiesz si, e Clojure:  jest jzykiem funkcyjnym;  jest Lispem na maszyny JVM;  ma specjalne mechanizmy do obsugi wspóbienoci.

Wszystkie te cechy s wane, jednak adna z nich nie odgrywa najwaniejszej roli. Naszym zdaniem najistotniejszymi aspektami jzyka Clojure s jego prostota i moliwoci. Prostota w kontekcie oprogramowania jest wana z kilku wzgldów, tu jednak mamy na myli pierwotne i najwaniejsze znaczenie tego sowa — proste jest to, co nie jest zoone. Proste komponenty umoliwiaj systemowi przeprowadzanie operacji zaplanowanych przez projektantów i nie wykonuj czynnoci niepowizanych z danym zadaniem. Z naszych dowiadcze wynika, e niewielka zoono zwykle szybko przeksztaca si w niebezpiecznie powan. Take sowo moliwoci ma wiele znacze. Tu mamy na myli zdolno do wykonywania stawianych aplikacji zada. Aby programista mia odpowiednie moliwoci, musi wykorzysta platform, która sama je posiada i jest powszechnie dostpna. Tak platform jest na przykad maszyna JVM. Ponadto uywane narzdzia musz zapewnia peny, nieograniczony dostp do oferowanych moliwoci. Dostp do moliwoci jest czsto podstawowym wymogiem w projektach, w których trzeba w peni wykorzysta platform.

Kup książkę

Poleć książkę


24



Programowanie w jzyku Clojure

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

1.1. Dlaczego Clojure? Wszystkie charakterystyczne cechy jzyka Clojure maj zapewnia prostot, moliwoci lub i jedno, i drugie. Oto kilka przykadów:  Programowanie funkcyjne jest proste, poniewa pozwala oddzieli obliczenia od stanu i tosamoci. Zalet jest to, e programy funkcyjne s atwiejsze do zrozumienia, pisania, testowania, optymalizowania i równolegego wykonywania.  Konstrukcje umoliwiajce wspódziaanie jzyków Clojure i Java daj due moliwoci, poniewa zapewniaj bezporedni dostp do skadni Javy. Zalet jest to, e mona uzyska wydajno na poziomie Javy i stosowa skadni charakterystyczn dla tego jzyka. Co waniejsze, nie trzeba ucieka si do jzyka niszego poziomu, aby zapewni sobie dodatkowe moliwoci.  Lisp jest prosty w dwóch bardzo wanych aspektach — oddziela wczytywanie od wykonania, a jego skadnia obejmuje niewielk liczb niezalenych elementów. Zalet jest to, e wzorce projektowe s ujte w abstrakcyjne konstrukcje skadniowe, a S-wyraenia obejmuj kod w jzykach XML, JSON i SQL.  Lisp daje te due moliwoci, poniewa udostpnia kompilator i system makr dziaajcy w czasie wykonywania programu. Zalet jest to, e w Lispie wystpuje pó ne wizanie i mona atwo tworzy jzyki DSL.  Model czasu w jzyku Clojure jest prosty. Oddzielono w nim wartoci, tosamo, stan i czas. Zalet jest to, e w programach mona sprawdza i zapamitywa informacje bez obaw o to, e starsze dane zostan nadpisane.  Protokoy s proste. W Clojure polimorfizm jest niezaleny od dziedziczenia. Zalet jest to, e mona bezpiecznie i w konkretnym celu rozszerza typy oraz abstrakcje. Nie wymaga to stosowania zawiych wzorców projektowych lub wprowadzania zmian w cudzym kodzie (co czsto prowadzi do bdów).

Kup książkę

Poleć książkę


Rozdzia 1. • Wprowadzenie



25

Ta lista cech stanowi „map” pomocn w dalszych rozdziaach ksiki. Nie martw si, jeli na razie nie rozumiesz wszystkich szczegóów. Kadej z tych cech powicamy cay rozdzia. Zobaczmy, jak niektóre z tych cech sprawdzaj si w praktyce. Zbudujmy w tym celu prost aplikacj. Przy okazji dowiesz si, jak wczytywa i wykonywa wiksze przykadowe programy, które prezentujemy dalej w ksice.

Jzyk Clojure jest elegancki W jzyku Clojure stosunek sygnau do szumu jest wysoki. Dlatego programy pisane w tym jzyku s krótkie. Takie programy s tasze w tworzeniu, instalowaniu i konserwacji1. Jest to prawd zwaszcza wtedy, gdy programy s zwize, a nie tylko treciwe. Przyjrzyj si na przykad poniszemu kodowi w Javie (pochodzi on z projektu Apache Commons): data/snippets/isBlank.java

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

Metoda isBlank() sprawdza, czy acuch znaków jest pusty (nie zawiera adnych znaków lub obejmuje same odstpy). Oto kod podobnej metody w jzyku Clojure: src/examples/introduction.clj

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

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

Software Estimation: Demystifying the Black Art [McC06] to znakomita ksika. Jej autorzy dowodz, e krótsze jest tasze.

Kup książkę

Poleć książkę


26



Programowanie w jzyku Clojure

jako argumenty i (lub) zwracaj funkcje. Funkcja every? przyjmuje funkcj i kolekcj, a zwraca warto true, jeli otrzymana funkcja zwraca true dla kadego elementu z kolekcji. Poniewa w wersji w jzyku Clojure nie ma rozgazie, kod jest bardziej czytelny i atwiejszy do przetestowania. Zalety te s jeszcze wyra niejsze w wikszych programach. Ponadto, cho kod jest zwizy, mona go atwo zrozumie. Program w jzyku Clojure mona potraktowa jak definicj pustego acucha znaków — jest to acuch, w którym kady znak jest odstpem. Kod ten jest znacznie lepszy od metody z projektu Commons, w którym definicja pustego acucha znaków jest ukryta za szczegóowym kodem ptli i instrukcji if. Oto inny przykad. Przyjrzyj si banalnej klasie Person napisanej w jzyku Java: data/snippets/Person.java

public class Person { private String firstName; private String lastName; public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }

W jzyku Clojure rekord Person mona zdefiniowa w jednym wierszu: (defrecord Person [first-name last-name])

Korzysta z tego rekordu mona tak: (def foo (->Person "Aaron" "Bedra")) -> #'user/foo foo -> #:user.Person{:first-name "Aaron", :last-name "Bedra"}

Kup książkę

Poleć książkę


Rozdzia 1. • Wprowadzenie



27

Instrukcj defrecord i powizane funkcje omawiamy w podrozdziale 6.3, „Protokoy”. Kod w jzyku Clojure nie tylko jest znacznie krótszy; rekord Person jest tu niezmienny. Niezmienne struktury danych s z natury bezpieczne ze wzgldu na wtki, a mechanizmy modyfikowania danych mona utworzy w odrbnej warstwie za pomoc referencji, agentów i atomów jzyka Clojure. Techniki te omawiamy w rozdziale 5., „Stan”. Poniewa rekordy s niezmienne, jzyk Clojure automatycznie udostpnia poprawne implementacje funkcji hashCode() i equals(). Jzyk Clojure ma wbudowanych wiele eleganckich rozwiza, jeli jednak stwierdzisz, e czego Ci w nim brakuje, moesz samodzielnie doda potrzebne mechanizmy. Umoliwiaj to cechy Lispa.

Clojure to odwieony Lisp Clojure jest Lispem. Od dziesicioleci zwolennicy Lispa mówi o przewagach, jakie jzyk ten ma w porównaniu z waciwie wszystkimi innymi jzykami. Plan opanowania wiata przez Lispa jest jednak realizowany do powoli. Twórcy jzyka Clojure, podobnie jak autorzy kadej odmiany Lispa, musieli zmierzy si z dwoma problemami. Oto one:  Clojure ma odnie sukces jako odmiana Lispa. Wymaga to przekonania uytkowników Lispa, e Clojure obejmuje najwaniejsze mechanizmy swojego poprzednika.  Jednoczenie Clojure ma odnie sukces tam, gdzie wczeniejsze wersje Lispa si nie przyjy. Wymaga to zdobycia poparcia wikszej spoecznoci programistów. Autorzy jzyka Clojure radz sobie z tymi problemami przez udostpnienie mechanizmów metaprogramowania (charakterystycznych dla Lispa) i wprowadzenie zestawu usprawnie skadniowych uatwiajcych stosowanie jzyka Clojure programistom, którzy nie znaj Lispa.

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

Kup książkę

Poleć książkę


28



Programowanie w jzyku Clojure

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

W kodzie wystpuje metoda getFirstName(). Metody s polimorficzne i mona je dostosowa do potrzeb. Jednak znaczenie kadego innego sowa w przykadowym kodzie jest okrelane przez jzyk. Czasem wygodna jest moliwo zmiany znaczenia poszczególnych sów. Pozwala to na przykad:  zdefiniowa sowo private jako „prywatne w kodzie produkcyjnym, ale publiczne na potrzeby serializacji i testów jednostkowych”;  zdefiniowa sowo class w taki sposób, aby platforma automatycznie generowaa metody pobierajce i ustawiajce dla pól prywatnych (o ile programista nie zarzdzi inaczej);  utworzy podklas dla class i umieci w niej wywoywane zwrotnie uchwyty dla zdarze cyklu ycia; klasa z obsug cyklu ycia moe na przykad zgasza zdarzenie utworzenia egzemplarza tej klasy. Natykalimy si na programy, w których potrzebne byy wszystkie te cechy. Bez potrzebnych mechanizmów programici musieli ucieka si do powtarzalnych i podatnych na bdy sztuczek. Aby poradzi sobie z brakiem niezbdnych rozwiza, napisano dosownie miliony wierszy kodu. W wikszoci jzyków trzeba poprosi osoby odpowiedzialne za implementacj, aby doday wspomniane wczeniej mechanizmy. W Clojure moesz samodzielnie doda potrzebne cechy, piszc makra (rozdzia 7., „Makra”). Nawet sam jzyk Clojure jest zbudowany za pomoc makr, takich jak defrecord: (defrecord name [arg1 arg2 arg3])

Jeli chcesz zmieni znaczenie sowa, moesz napisa wasne makro. Jeeli potrzebujesz rekordów o cisej kontroli typów i z opcjonalnym sprawdzaniem, czy pola nie maj wartoci null, wystarczy utworzy wasne makro defrecord. Powinno ono wyglda tak: (defrecord name [Type :arg1 Type :arg2 Type :arg3] :allow-nulls false)

Moliwo zmiany dziaania jzyka w nim samym jest wyjtkow zalet Lispa. Mona znale  wiele opisów rónych aspektów tego podejcia: 2  Lisp jest homoikoniczny . Oznacza to, e kod w Lispie to dane. Dlatego atwo jest tworzy programy za pomoc innych programów. 2

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

Kup książkę

Poleć książkę


Rozdzia 1. • Wprowadzenie 



29

Cay jzyk jest dostpny w kadym momencie. Paul Graham w artykule Revenge of the Nerds3 wyjania, dlaczego jest to wane.

Skadnia Lispa eliminuje te problemy z priorytetami operatorów i cznoci operacji. W ksice tej nie znajdziesz tabel dotyczcych tych zagadnie. Z uwagi na wymóg stosowania nawiasów wyraenia s jednoznaczne. Wad prostej, jednolitej skadni Lispa (przynajmniej dla pocztkujcych) jest nacisk na nawiasy i listy (listy to gówny typ danych w Lispie). Clojure udostpnia ciekawe poczenie cech, które uatwiaj uywanie Lispa programistom znajcym inne jzyki.

Lisp z mniejsz liczb nawiasów Clojure zapewnia istotne zalety programistom uywajcym innych odmian Lispa. Oto te korzyci:  W jzyku Clojure fizyczne listy z Lispa s uogólnione do abstrakcyjnej postaci — sekwencji. Pozwala to zachowa moliwoci, jakie daj listy, a przy tym wykorzysta ich zalety w innych strukturach danych.  Wykorzystanie maszyn JVM jako podstawy dla kodu w jzyku Clojure daje dostp do standardowej biblioteki i bardzo popularnej platformy.  Sposób analizowania symboli i cudzysowów sprawia, e w jzyku Clojure pisanie standardowych makr jest stosunkowo proste. Wielu uytkowników jzyka Clojure nie zna Lispa, za to prawdopodobnie syszao niepochlebne opinie na temat stosowania w nim nawiasów. W jzyku Clojure zachowano nawiasy (i moliwoci Lispa!), jednak pod kilkoma wzgldami usprawniono tradycyjn skadni Lispa.  Clojure zapewnia wygodn, opart na literaach skadni dla rónych struktur danych (nie tylko dla list), takich jak wyraenia regularne, odwzorowania, zbiory, wektory i metadane. Dlatego kod w jzyku Clojure jest mniej zaleny od list ni w wikszoci innych odmian Lispa. Midzy innymi parametry funkcji s podawane w wektorach, [], a nie w listach, (). src/examples/introduction.clj

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

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

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

Kup książkę

Poleć książkę




30 

Programowanie w jzyku Clojure

W jzyku Clojure, inaczej ni w wikszoci odmian Lispa, przecinki s traktowane jak odstpy. ; Wektory przypominaj tablice z innych jzyków. [1, 2, 3, 4] -> [1 2 3 4]



Jzyk Clojure jest idiomatyczny i nie wymaga niepotrzebnego zagniedania nawiasów. Przyjrzyj si makru cond, które wystpuje zarówno w Common Lispie, jak i w Clojure. Makro cond sprawdza zestaw par test-wynik i zwraca pierwszy wynik, dla którego warto wyraenia testowego to true. Kada para test-wynik znajduje si w nawiasach: ; Makro cond w Common Lispie. (cond ((= x 10) "equal") ((> x 10) "more"))

W jzyku Clojure dodatkowe nawiasy s niepotrzebne. ; Makro cond w Clojure. (cond (= x 10) "equal" (> x 10) "more")

Jest to kwestia czysto estetyczna i oba podejcia maj swoich zwolenników. Wane jest to, e jzyk Clojure pozbawiono uciliwych aspektów Lispa, jeli byo to moliwe bez utraty zalet tego ostatniego. Clojure jest wietn odmian Lispa zarówno dla ekspertów, jak i dla pocztkujcych programistów Lispa.

Clojure to jzyk funkcyjny Clojure jest jzykiem funkcyjnym, natomiast nie jest (w odrónieniu od Haskella) czysto funkcyjny. Oto cechy jzyków funkcyjnych:  Funkcje to penoprawne obiekty. Oznacza to, e funkcje mona tworzy w czasie wykonywania programu, przekazywa, zwraca i ogólnie uywa ich jak wszelkich innych typów danych.  Dane s niezmienne.  Funkcje s czyste, czyli nie maj efektów ubocznych. W wielu obszarach programy funkcyjne s atwiejsze do zrozumienia, mniej podatne na bdy i znacznie atwiejsze do wielokrotnego uytku. Na przykad poniszy krótki program wyszukuje w bazie danych utwory kadego kompozytora, który napisa dzieo pod tytuem „Requiem”: (for [c compositions :when (= "Requiem" (:name c))] (:composer c)) -> ("W. A. Mozart" "Giuseppe Verdi")

Kup książkę

Poleć książkę


Rozdzia 1. • Wprowadzenie



31

Sowo for nie jest pocztkiem ptli, ale wyraenia listowego (ang. list comprehension). Kod ten oznacza „dla kadego c z kolekcji compositions, gdzie nazw c jest "Requiem", podaj kompozytora c”. Wyraenia listowe omawiamy w punkcie „Przeksztacanie sekwencji”. Przykadowy kod ma cztery podane cechy:  Jest prosty. Nie obejmuje ptli, zmiennych ani zmiennego stanu.  Jest bezpieczny ze wzgldu na wtki. Nie wymaga stosowania blokad.  Jest moliwy do równolegego wykonywania. Kady krok mona przydzieli do odrbnego wtku bez koniecznoci modyfikowania kodu poszczególnych kroków.  Jest uniwersalny. Kolekcj compositions moe by zwyky zbiór, kod w XML-u lub zbiór wyników z bazy danych. Warto porówna programy funkcyjne z programami imperatywnymi, w których instrukcje zmieniaj stan programu. Wikszo programów obiektowych pisze si w stylu imperatywnym, dlatego nie maj one adnych z wymienionych wczeniej zalet. S niepotrzebnie skomplikowane, niebezpieczne ze wzgldu na wtki, nie umoliwiaj równolegego dziaania, a kod jest trudny do uogólnienia. Bezporednie porównanie podejcia funkcyjnego i imperatywnego znajdziesz w podrozdziale 2.7, „Gdzie si podziaa ptla for?”. Programici znaj zalety jzyków funkcyjnych ju od dugiego czasu. Jednak jzyki funkcyjne, na przykad Haskell, nie zdobyy dominujcej pozycji. Wynika to z tego, e nie wszystkie operacje mona wygodnie wykona w podejciu czysto funkcyjnym. S cztery powody, dla których jzyk Clojure moe zyska wiksze zainteresowanie ni dawne jzyki funkcyjne:  Podejcie funkcyjne jest dzi bardziej przydatne ni kiedykolwiek wczeniej. Pojawiaj si maszyny o coraz wikszej liczbie rdzeni, a jzyki funkcyjne pozwalaj atwo wykorzysta moliwoci takiego sprztu. Programowanie funkcyjne omawiamy w rozdziale 4., „Programowanie funkcyjne”.  W jzykach funkcyjnych niewygodnie zarzdza si stanem, jeli musi si on zmienia. Clojure udostpnia mechanizmy do obsugi zmiennego stanu za pomoc programowej pamici transakcyjnej i referencji, agentów, atomów i wizania dynamicznego.

Kup książkę

Poleć książkę




32 



Programowanie w jzyku Clojure

W wielu jzykach funkcyjnych typy s okrelane statycznie. W jzyku Clojure stosuje si dynamiczne okrelanie typów, co uatwia zadanie programistom poznajcym dopiero programowanie funkcyjne. Wywoywanie w jzyku Clojure kodu Javy nie odbywa si w modelu funkcyjnym. Przy korzystaniu z Javy wkraczamy w znany wiat zmiennych obiektów. Zapewnia to wygod pocztkujcym, którzy ucz si programowania funkcyjnego, a take pozwala w razie potrzeby zrezygnowa z podejcia funkcyjnego. Wywoywanie kodu Javy opisujemy w rozdziale 9., „Sztuczki z Jav”.

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

Clojure upraszcza programowanie wspóbiene Mechanizmy programowania funkcyjnego dostpne w Clojure uatwiaj pisanie kodu bezpiecznego ze wzgldu na wtki. Poniewa niezmienne struktury danych nigdy si nie zmieniaj, nie wystpuje zagroenie uszkodzeniem danych w wyniku dziaania innych wtków. Jednak obsuga wspóbienoci w Clojure wykracza poza mechanizmy programowania funkcyjnego. Jeli potrzebne s referencje do zmiennych danych, Clojure zabezpiecza je za pomoc programowej pamici transakcyjnej (ang. software transactional memory — STM). STM suy do tworzenia kodu bezpiecznego ze wzgldu na wtki i jest rozwizaniem wyszego poziomu ni blokady z Javy. Zamiast stosowa podatne na bdy strategie blokowania danych, mona zabezpieczy wspóuytkowany stan za pomoc transakcji. Jest to duo lepsze podejcie, poniewa wielu programistów dobrze zna transakcje z uwagi na dowiadczenie w korzystaniu z baz danych. Poniszy kod tworzy dziaajc, bezpieczn ze wzgldu na wtki baz danych z kontami przechowywan w pamici: (def accounts (ref #{})) (defrecord Account [id balance])

Funkcja ref tworzy zabezpieczon za pomoc transakcji referencj do biecego stanu bazy danych. Aktualizowanie stanu jest niezwykle proste. Poniej pokazujemy, jak doda do bazy nowe konto: (dosync (alter accounts conj (->Account "CLJ" 1000.00)))

Kup książkę

Poleć książkę


Rozdzia 1. • Wprowadzenie



33

Instrukcja dosync powoduje aktualizowanie bazy accounts w transakcji. Rozwizanie to zapewnia bezpieczestwo ze wzgldu na wtki i jest atwiejsze w stosowaniu od blokad. Dziki transakcjom nigdy nie trzeba martwi si o to, które obiekty i w jakiej kolejnoci naley zablokowa. Podejcie transakcyjne sprawdza si lepiej take w niektórych standardowych zastosowaniach. Przykadowo: w modelu tym wtki wczytujce dane nigdy nie musz blokowa danych. Cho przedstawiony przykad jest bardzo prosty, technika jest ogólna i sprawdza si take w praktyce. Wicej informacji o wspóbienoci i pamici STM w jzyku Clojure znajdziesz w rozdziale 5., „Stan”.

Wykorzystanie maszyny JVM w Clojure Clojure zapewnia przejrzysty, prosty i bezporedni dostp do Javy. W kodzie mona bezporednio wywoa metody z dowolnego interfejsu API Javy: (System/getProperties) -> {java.runtime.name=Java(TM) SE Runtime Environment ... i wiele innych ...

Clojure obejmuje wiele skadniowych mechanizmów do wywoywania kodu w Javie. Nie omawiamy tu ich szczegóowo (zobacz podrozdzia 2.5, „Wywoywanie kodu w Javie”), warto jednak wspomnie, e w Clojure wystpuje mniej kropek i mniej nawiasów ni w analogicznym kodzie Javy: // Java "hello".getClass().getProtectionDomain() ; Clojure (.. "hello" getClass getProtectionDomain)

Clojure udostpnia proste funkcje do implementowania interfejsów Javy i tworzenia klas pochodnych od klas Javy. Ponadto wszystkie funkcje jzyka Clojure obejmuj implementacj interfejsów Callable i Runnable. Dlatego mona atwo przekaza ponisz funkcj anonimow do konstruktora klasy Thread Javy: (.start (new Thread (fn [] (println "Witaj" (Thread/currentThread))))) -> Witaj #<Thread Thread[Thread-0,5,main]>

Dziwne dane wyjciowe wynikaj ze sposobu wywietlania informacji o obiektach Javy w jzyku Clojure. Thread to nazwa klasy danego obiektu, a czon Thread[Thread-0,5,main] to efekt wywoania metody toString obiektu. (Zauwa, e w przedstawionym kodzie nowy wtek dziaa a do zakoczenia pracy, natomiast jego dane wyjciowe mog w dziwny sposób przeplata si z wierszami zachty rodowiska REPL. Nie jest to problem z jzykiem Clojure, a jedynie wynik zapisywania danych do strumienia wyjcia przez wicej ni jeden wtek).

Kup książkę

Poleć książkę


34



Programowanie w jzyku Clojure

Poniewa skadnia do wywoywania kodu Javy w Clojure jest przejrzysta i prosta, zwykle uywa si Javy bezporednio, zamiast ukrywa kod w tym jzyku za charakterystycznymi dla Lispa nakadkami. Poznae ju kilka powodów do stosowania jzyka Clojure. Pora przystpi do pisania kodu.

1.2. Szybkie wprowadzenie do programowania w Clojure Aby uruchomi rodowisko jzyka Clojure i kod z tej ksiki, potrzebujesz dwóch rzeczy. Oto one: 4  rodowisko uruchomieniowe Javy. Pobierz i zainstaluj Jav w wersji 5. lub nowszej. W wersji 6. znacznie poprawiono wydajno i system informowania o wyjtkach, dlatego warto stosowa wanie j. 5  Leiningen . Leiningen to narzdzie do zarzdzania zalenociami i uruchamiania operacji na kodzie. Jest to take najpopularniejsze w wiecie jzyka Clojure narzdzie do wykonywania tych zada. Leiningen posuy do zainstalowania jzyka Clojure i wszystkich elementów wymaganych w przykadowym kodzie. Jeli masz ju zainstalowane narzdzie Leiningen, wiesz zapewne, jak z niego korzysta. Jeeli jeszcze nie masz potrzebnej wiedzy, zapoznaj si z krótkim wprowadzeniem ze strony narzdzia w serwisie GitHub6. Znajdziesz tam instrukcje dotyczce instalacji, a take podstawowe informacje na temat uytkowania Leiningena. Nie musisz jednak uczy si wszystkiego, poniewa w ksice opisujemy polecenia potrzebne do uruchomienia przykadów. W trakcie pracy z ksik korzystaj z jzyka Clojure w wersji waciwej dla przykadowego kodu. Po przeczytaniu ksiki moesz zastosowa si do instrukcji z ramki „Samodzielne budowanie jzyka Clojure” i zbudowa aktualn wersj jzyka.

4 5 6

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

Kup książkę

Poleć książkę


Rozdzia 1. • Wprowadzenie



35

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

Samodzielne budowanie jzyka Clojure Moliwe, e chcesz zbudowa jzyk Clojure na podstawie kodu ródowego, aby uzyska nowe funkcje i wprowadzi poprawki bdów. Mona zrobi to w nastpujcy sposób: git clone git://github.com/clojure/clojure.git cd clojure mvn package

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

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

Po udanym uruchomieniu rodowiska REPL powinien pojawi si wiersz zachty z tekstem user=>: Clojure user=>

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

Korzystanie ze rodowiska REPL Aby pokaza, jak korzysta ze rodowiska REPL, tworzymy kilka wersji kodu wywietlajcego tekst „Witaj, wiecie”. Najpierw wpisz kod (println "Witaj, wiecie") w wierszu zachty rodowiska REPL. user=> (println "Witaj, wiecie") -> Witaj, wiecie

Kup książkę

Poleć książkę


36



Drugi wiersz, Witaj,

Programowanie w jzyku Clojure wiecie,

to dane dane wyjciowe z konsoli.

Teraz umiemy kod w funkcji, która potrafi „zwraca si” do uytkownika po imieniu. (defn hello [name] (str "Witaj, " name)) -> #'user/hello

Rozómy ten kod na fragmenty. Oto one:  defn suy do definiowania funkcji;  hello to nazwa funkcji;  funkcja hello przyjmuje jeden argument, name;  str to wywoanie funkcji czcej dowoln list argumentów w acuch znaków;  defn, hello, name i str to symbole, czyli nazwy prowadzce do rónych elementów; dozwolone symbole opisujemy w punkcie „Symbole”. Przyjrzyj si zwracanej wartoci, #'user/hello. Przedrostek #' oznacza, e funkcj zapisano w zmiennej jzyka Clojure, a user to przestrze nazw, w której znajduje si ta funkcja. Jest to domylna przestrze nazw w rodowisku REPL, odpowiadajca domylnemu pakietowi w Javie. Na razie zmienne i przestrzenie nazw nie maj znaczenia. Omawiamy je w podrozdziale 2.4, „Zmienne, wizanie i przestrzenie nazw”. Teraz mona wywoa funkcj hello i przekaza do niej imi. user=> (hello "Janku") -> "Witaj, Janku"

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

Specjalne zmienne rodowisko REPL obejmuje szereg przydatnych zmiennych specjalnych. W czasie pracy w rodowisku REPL wyniki obliczania trzech ostatnich wyrae znajduj si w specjalnych zmiennych *1, *2 i *3. Pozwala to na wygodn prac w modelu iteracyjnym. Spróbujmy poczy kilka powita. user=> (hello "Janku") -> "Witaj, Janku" user=> (hello "Clojure") -> "Witaj, Clojure"

Kup książkę

Poleć książkę




Rozdzia 1. • Wprowadzenie

37

Teraz mona zastosowa specjalne zmienne do poczenia wyników ostatnich instrukcji. (str *1 " i " *2) -> "Witaj, Clojure i Witaj, Janku"

Popenienie bdu w rodowisku REPL prowadzi do zgoszenia wyjtku Javy (z uwagi na zwizo szczegóy pomijamy). Niedozwolone jest na przykad dzielenie przez zero. user=> (/ 1 0) -> ArithmeticException Divide by zero clojure.lang.Numbers.divide

Tu problem jest oczywisty, jednak czasem jest bardziej skomplikowany i potrzebujemy szczegóowego stosu wywoa. W specjalnej zmiennej *e znajduj si informacje o ostatnim wyjtku. Poniewa wyjtki w Clojure s wyjtkami Javy, mona wywietli stos wywoa za pomoc instrukcji pst (od ang. print stacktrace, czyli wywietl stos wywoa)7. user=> (pst) -> ArithmeticException Divide by zero | clojure.lang.Numbers.divide | sun.reflect.NativeMethodAccessorImpl.invoke0 | sun.reflect.NativeMethodAccessorImpl.invoke | sun.reflect.DelegatingMethodAccessorImpl.invoke | java.lang.reflect.Method.invoke | clojure.lang.Reflector.invokeMatchingMethod | clojure.lang.Reflector.invokeStaticMethod | user/eval1677 | clojure.lang.Compiler.eval | clojure.lang.Compiler.eval | clojure.core/eval

Wspódziaanie z Jav omawiamy w rozdziale 9., „Sztuczki z Jav”. Jeli blok kodu jest zbyt dugi, aby mona go wygodnie wpisa w rodowisku REPL, umie kod w pliku, a nastpnie wczytaj ten plik w rodowisku. Moesz uy cieki bezwzgldnej lub poda j wzgldem miejsca uruchomienia rodowiska REPL. ; Zapisz kod w pliku temp.clj, a nastpnie wywoaj instrukcj: user=> (load-file "temp.clj")

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

7

Instrukcja pst jest dostpna tylko w Clojure 1.3.0 i nowszych wersjach.

Kup książkę

Poleć książkę




38

Programowanie w jzyku Clojure

Dodawanie stanu wspóuytkowanego Funkcja hello z poprzedniego przykadu to czysta funkcja, czyli taka, której dziaanie nie ma efektów ubocznych. Czyste funkcje atwo si pisze i testuje. S take atwe do zrozumienia, dlatego w wielu sytuacjach warto je stosowa. Jednak w wikszoci programów wystpuje wspóuytkowany stan, a do zarzdzania nim su funkcje typu impure (czyli takie, które nie s czyste). Dodajmy do funkcji hello mechanizm ledzenia liczby uytkowników. Najpierw trzeba utworzy struktur danych do przechowywania tej liczby. Uyjmy do tego zbioru. #{} -> #{}

#{}

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

(conj coll item)

Instrukcja conj (od ang. conjoin, czyli czy) tworzy now kolekcj z dodawanym elementem. Doczmy element do zbioru, aby upewni si, e powstaje nowy zbiór. (conj #{} "Janku") -> #{"Janku"}

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

Aby okreli nazw atomu, naley uy instrukcji def. (def symbol initial-value?)

Instrukcja def przypomina polecenie defn, ale jest ogólniejsza. Przy jej uyciu mona definiowa funkcje lub dane. Uyjmy sowa atom do utworzenia atomu i instrukcji def do powizania atomu z nazw visitors. (def visitors (atom #{})) -> #'user/visitors

Aby zaktualizowa referencj, trzeba uy funkcji, na przykad swap!. (swap! r update-fn & args)

Funkcja swap! przeprowadza operacj update-fn na referencji r i w razie potrzeby uywa przy tym opcjonalnych argumentów args. Spróbujmy wstawi uytkownika do kolekcji visitors, uywajc do aktualizowania funkcji conj. (swap! visitors conj "Janku") -> #{"Janku"}

Kup książkę

Poleć książkę


Rozdzia 1. • Wprowadzenie



39

atom to tylko jeden z kilku typów referencyjnych dostpnych w jzyku Clojure. Wybór odpowiedniego typu referencyjnego nie jest prosty (zagadnienie to omawiamy w rozdziale 5., „Stan”).

W dowolnym momencie mona sprawdzi zawarto pamici, do której prowadzi referencja. Suy do tego instrukcja deref lub jej krótszy odpowiednik, @. (deref visitors) -> #{"Janku"} @visitors -> #{"Janku"}

Teraz mona zbudowa now, bardziej rozbudowan wersj funkcji hello. src/examples/introduction.clj

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

Teraz sprawd my, czy uytkownicy s poprawnie zapisywani w pamici. (hello "Marku") -> "Witaj, Marku" @visitors -> #{"Jacku" "Janku" "Marku"}

Na Twoim komputerze lista uytkowników bdzie prawdopodobnie inna. Na tym wanie polega problem ze stanem. Efekty s róne w zalenoci od tego, kiedy zaszy dane zdarzenia. Zrozumie funkcj mona na podstawie jej analizy. Aby zrozumie stan, trzeba pozna ca histori dziaania programu. Jeli to moliwe, unikaj przechowywania stanu. Jeeli jest to niemoliwe, dbaj o to, aby stanem mona byo zarzdza. Uywaj do tego typów referencyjnych, na przykad atomów. Atomy (i wszystkie inne typy referencyjne w Clojure) s bezpieczne przy korzystaniu z wielu wtków i procesorów. Co lepsze, zapewnienie bezpieczestwa nie wymaga stosowania blokad, które bywaj skomplikowane w uyciu. Na tym etapie powiniene umie ju wprowadza krótkie fragmenty kodu w rodowisku REPL. Wprowadzanie wikszych porcji kodu odbywa si podobnie. Take biblioteki jzyka Clojure mona wczytywa i uruchamia z poziomu rodowiska REPL. Dalej pokazujemy, jak to zrobi.

Kup książkę

Poleć książkę


40



Programowanie w jzyku Clojure

1.3. Biblioteki jzyka Clojure Kod jzyka Clojure jest umieszczony w bibliotekach. Kada biblioteka jzyka Clojure znajduje si w przestrzeni nazw, która jest odpowiednikiem pakietu Javy. Bibliotek jzyka Clojure mona wczyta za pomoc instrukcji require. (require quoted-namespace-symbol)

Jeli programista da biblioteki o nazwie clojure.java.io, Clojure szuka pliku o nazwie clojure/java/io.clj w ciece ze zmiennej CLASSPATH. Zobaczmy, jaki jest tego efekt. user=> (require 'clojure.java.io) -> nil

Pocztkowy pojedynczy apostrof (') jest niezbdny i suy do dosownego podawania (ang. quoting) nazwy biblioteki (podawanie nazw omawiamy w podrozdziale 2.2, „Makra odczytu”). Zwrócona warto nil oznacza powodzenie. Przy okazji sprawd , czy moesz wczyta przykadowy kod do tego rozdziau (bibliotek examples.introduction). user=> (require 'examples.introduction) -> nil

Biblioteka examples.introduction obejmuje implementacj generowania liczb Fibonacciego. W jzykach funkcyjnych jest to tradycyjny program typu „Witaj, wiecie”. Liczby Fibonacciego omawiamy szczegóowo w podrozdziale 4.2, „»Leniwe« podejcie”. Na razie upewnij si, e moesz uruchomi przykadow funkcj fibs. Wprowad poniszy wiersz kodu w rodowisku REPL, a otrzymasz 10 pierwszych liczb Fibonacciego. (take 10 examples.introduction/fibs) -> (0 1 1 2 3 5 8 13 21 34)

Jeli otrzymae 10 pierwszych liczb Fibonacciego (wymienionych powyej), poprawnie zainstalowae przykadowy kod z ksiki. Wszystkie przykady sprawdzilimy za pomoc testów jednostkowych (testy znajduj si w katalogu examples/test). Samych testów nie omawiamy w ksice, jednak mog okaza si przydatnym ródem wiedzy. Aby uruchomi testy jednostkowe, uyj instrukcji lein test.

Kup książkę

Poleć książkę


Rozdzia 1. • Wprowadzenie



41

Instrukcje require i use Po zadaniu biblioteki jzyka Clojure za pomoc instrukcji require elementy z biblioteki trzeba wskazywa za pomoc penej nazwy. Zamiast nazwy fibs trzeba uy okrelenia examples.introduction/fibs. Uruchom drugi egzemplarz rodowiska REPL8 i wprowad poniszy kod. (require 'examples.introduction) -> nil (take 10 examples.introduction/fibs) -> (0 1 1 2 3 5 8 13 21 34)

Wprowadzanie penych nazw szybko staje si kopotliwe. Moesz uy instrukcji refer dla przestrzeni nazw i odwzorowa wszystkie nazwy z tej przestrzeni na biec przestrze nazw. (refer quoted-namespace-symbol)

Wywoaj instrukcj refer dla przestrzeni examples.introduction i sprawd , czy moesz bezporednio wywoa funkcj fibs. (refer 'examples.introduction) -> nil (take 10 fibs) -> (0 1 1 2 3 5 8 13 21 34)

Wygodna funkcja use pozwala wykona instrukcje require i refer w jednym kroku. (use quoted-namespace-symbol)

W nowym rodowisku REPL wprowad nastpujce instrukcje. (use 'examples.introduction) -> nil (take 10 fibs) -> (0 1 1 2 3 5 8 13 21 34)

W trakcie pracy z przykadowym kodem z ksiki moesz wywoa instrukcj require lub use z opcj :reload, aby wymusi ponowne wczytanie biblioteki. (use :reload 'examples.introduction) -> nil

Opcja :reload jest przydatna, jeli wprowadzasz zmiany i chcesz sprawdzi ich efekt bez ponownego uruchamiania rodowiska REPL. 8

Otwarcie nowego rodowiska REPL zapobiega konfliktom nazw midzy utworzonym wczeniej kodem a funkcjami o tych samych nazwach z przykadowego kodu. W praktyce nie stanowi to problemu. Zagadnienie to omawiamy w punkcie „Przestrzenie nazw”.

Kup książkę

Poleć książkę


42



Programowanie w jzyku Clojure

Znajdowanie dokumentacji Potrzebna dokumentacja czsto jest dostpna bezporednio w rodowisku REPL. Najprostsz funkcj pomocnicz9 jest doc. (doc name)

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

Pierwszy wiersz danych wyjciowych funkcji doc obejmuje pen nazw sprawdzanej funkcji. W drugim znajduj si argumenty generowane bezporednio w kodzie. Wybrane czsto stosowane nazwy argumentów i ich zastosowanie omawiamy w ramce „Zwyczajowe nazwy parametrów”. Dalsze wiersze obejmuj a cuch znaków dokumentacji, jeli jest on podany w definicji funkcji. Zwyczajowe nazwy parametrów acuchy znaków dokumentacji w funkcjach reduce i areduce obejmuj szereg krótkich nazw parametrów. Oto niektórych z tych nazw i sposoby ich stosowania. Parametr a agt coll expr f idx r v val

Zastosowanie Tablica Javy Agent Kolekcja Wyraenie Funkcja Indeks Referencja Wektor Warto 

Nazwy mog wydawa si krótkie, jednak jest tak nie bez powodu — „dobre” nazwy czsto s ju „zajte” przez funkcje jzyka Clojure! Uywanie dla parametrów nazw identycznych z nazwami funkcji jest dopuszczalne, ale uznaje si to za oznak zego stylu. Parametr zasania wtedy funkcj, dlatego jest ona niedostpna, kiedy parametr znajduje si w zasigu programu. Dlatego nie naley nazywa referencji ref, agentów agent, a liczników — count, poniewa s to nazwy funkcji. 9

Tak naprawd doc to makro jzyka Clojure.

Kup książkę

Poleć książkę




Rozdzia 1. • Wprowadzenie

43

acuch znaków dokumentacji mona doda do funkcji przez umieszczenie go bezporednio po jej nazwie. src/examples/introduction.clj

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

Czasem nie znasz nazwy elementu, którego dokumentacji potrzebujesz. Funkcja find-doc wyszukuje informacje o wszystkich elementach, dla których dane wyjciowe funkcji doc pasuj do przekazanego wyraenia regularnego lub acucha znaków. (find-doc s)

Za pomoc funkcji kolekcje.

find-doc

mona sprawdzi, w jaki sposób Clojure skraca

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

Funkcja reduce pozwala w skrócony sposób stosowa operacje do kolekcji jzyka Clojure. Omawiamy j w punkcie „Przeksztacanie sekwencji”. Funkcja areduce wspódziaa z tablicami Javy, a opisujemy j w punkcie „Korzystanie z kolekcji Javy”. Dua cz jzyka Clojure jest napisana w nim samym, dlatego lektura jego kodu ródowego to pouczajce zadanie. Kod ródowy funkcji jzyka Clojure mona wywietli za pomoc instrukcji source z biblioteki repl. (clojure.repl/source symbol)

Wywietlmy kod ródowy prostej funkcji identity. (use 'clojure.repl) (source identity) -> (defn identity "Returns its argument." {:added "1.0" :static true} [x] x)

Kup książkę

Poleć książkę


44



Programowanie w jzyku Clojure

Oczywicie, mona te uywa interfejsu API Reflection Javy. Metody class, ancestors , instance? i podobne pozwalaj sprawdzi model obiektowy Javy i informuj na przykad o tym, e kolekcje jzyka Clojure s jednoczenie kolekcjami Javy. (ancestors (class [1 2 3])) -> #{clojure.lang.ILookup clojure.lang.Sequential java.lang.Object clojure.lang.Indexed java.lang.Iterable clojure.lang.IObj clojure.lang.IPersistentCollection clojure.lang.IPersistentVector clojure.lang.AFn java.lang.Comparable java.util.RandomAccess clojure.lang.Associative clojure.lang.APersistentVector clojure.lang.Counted clojure.lang.Reversible clojure.lang.IPersistentStack java.util.List clojure.lang.IEditableCollection clojure.lang.IFn clojure.lang.Seqable java.util.Collection java.util.concurrent.Callable clojure.lang.IMeta java.io.Serializable java.lang.Runnable}

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

1.4. Podsumowanie Wanie zakoczye szybki przegld jzyka Clojure. Poznae dajc due moliwoci skadni tego jzyka i jego zwizki z Lispem, a take zobaczye, jak atwe jest wywoywanie w Clojure kodu Javy. Uruchomie jzyk Clojure w swoim rodowisku, a take napisae w rodowisku REPL krótkie programy ilustrujce programowanie funkcyjne i sucy do obsugi stanu model referencji. Pora przyjrze si caemu jzykowi.

Kup książkę

Poleć książkę


Skorowidz

A agenty, 158 bieca warto, 159 sprawdzanie poprawnoci, 160 transakcje, 161 tworzenie, 158 wykrywanie bdów, 160 algebra relacji, 110 Apache Ant, 244 atomy, 157 dereferencja, 157 tworzenie, 157 ustawienie wartoci, 157

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

C Clojure, 15, 23 aktualizacja, 261 aspekty, 23 biblioteki, 20, 40 drzewo waciwoci systemowych, 238 inspector, 238

Kup książkę

Lazytest, 286 math.combinatorics, 275 Midje, 286 sekwencje, 87 test, 239 test.generative, 278 cechy jzyka, 24, 209 czytnik, 46 makra odczytu, 55 edytory kodów, 297 funkcje, 56 czyste, 38 dodawanie sugestii typów, 253 impure, 38 wywoanie, 56 wyszego rzdu, 25 Java, 15, 33, 243 dostp, 243 interfejsy, 183, 255 javadoc, 70 kompilacja AOT, 248 konstrukcja new, 68 korzystanie z kolekcji, 258 mechanizm wywoa zwrotnych, 256 parsery SAX, 255 rodowisko uruchomieniowe, 34 tworzenie klas, 255

Poleć książkę


302



Clojure Java tworzenie poredników, 255 tworzenie tablic, 258 wykorzystanie moliwoci, 247 wywoywanie kodu, 68 wywoywanie metody, 69 jzyk funkcyjny, 30 cechy, 30 konstrukcje skadniowe, 24, 46 Leiningen, 34, 261 liczby cakowite, 248 operatory, 248 Lisp, 15, 24, 27 makra, 28, 201 taksonomia, 216 maszyny JVM, 29 metadane, 77 model czasu, 24 niezmienne struktury danych, 27 obsuga wyjtków, 244 kontrolowane wyjtki, 245 porzdkowanie zasobów, 245 reagowanie na wyjtki, 247 optymalizowanie wydajnoci, 250 dodawanie sugestii typów, 253 uywanie typów prostych, 250 pobieranie zalenoci, 261 poczenie z witryn, 261 programowanie, 16 funkcyjne, 18, 24, 115 ptle, 74 reguy, 120 wspóbiene, 32 protokoy, 24, 179, 184 przestrze nazw, 36, 61, 65 rejestrowanie informacji, 264 rekordy, 193 rozkadanie struktury, 63 moliwoci, 65 sekwencje, 29, 81 biblioteka, 87 cechy, 83

Kup książkę

Programowanie w jzyku Clojure

Java, 98 manipulowanie, 197 wymuszanie realizacji, 97 wyraenia listowe, 95 stan, 147 model aktualizacji, 163 model funkcyjny, 149 model referencyjny, 149 sterowanie przepywem, 70 instrukcje, 70 makra, 71 rekurencja, 72 rodowisko REPL, 35 zmienne specjalne, 36 tosamo, 147 typy referencyjne, 147 tworzenie aplikacji, 269 gra Clojurebreaker, 270 typy danych, 179, 188 cechy, 188 typy referencyjne, 38 atom, 38 warto, 147 wizania, 61 wielometody, 225 wspóbieno, 18, 32, 148 powody stosowania, 148 sytuacja wycigu, 149 zakleszczenie, 149 zmienne, 36, 61 cechy, 62

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

F funkcje, 56 anonimowe, 58 konstrukcja, 59 powody tworzenia, 58 stosowanie, 61 unikanie, 223

Poleć książkę




Skorowidz

bez sprawdzania przepenienia, 251 czciowe wywoanie, 134 czyste, 38, 116 niezmienne dane, 116 dodawanie sugestii typów, 253 efekty uboczne, 71 funkcje wyszego rzdu, 25 leniwe, 127 liczba argumentów, 57 listy, 105 acuchy znaków dokumentacji, 42 odwzorowania, 53, 106 tworzenie, 108 operatory matematyczne, 47 predykaty, 52, 56 przejrzyste referencyjnie, 118 memoizacja, 119 rozwinicie funkcji, 135 implementacja, 135 sekwencje, 83 filtrowanie, 91 predykaty, 92 przeksztacanie, 93 tworzenie, 88 wyraenia regularne, 100 sowa kluczowe, 54 wektory, 105 wizania, 62 zasig leksykalny, 63 wywoanie, 47, 56 notacja przedrostkowa, 47 notacja wrostkowa, 47 zbiory, 109 zoone, 134

H hermetyzacja, 119 efekty uboczne, 120 Heroku, 292 biblioteka, 293 git init, 293 git push, 294 plik Procfile, 292

Kup książkę

303

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

Poleć książkę


304



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

Kup książkę

Programowanie w jzyku Clojure

J Java, 15, 16, 243 interfejsy, 183 wady, 183 zalety, 183 klasy BigDecimal, 249 BigInteger, 249 Character, 50 ChunkedSeq, 84 Person, 26 Random, 68 StringUtils, 74 Thread, 33 WidgetFactory, 205 metody egzemplarza, 204 obsuga, 245 obsuga wyjtków, 244 kontrolowane wyjtki, 244 porzdkowanie zasobów, 245 sekwencje, 98 kolekcje sekwencyjne, 98 wywoywanie kodu, 68

K kod gry Snake, 169 interfejs GUI, 169, 175 aktualizowanie, 175 defmulti, 175 fill-point, 175 game, 176 game-panel, 175 paint, 175 proxy, 176 tworzenie nowej gry, 176 wywietlanie wa i jabka, 175 model funkcyjny, 169 add-points, 170, 171 assoc, 171 cons, 171 dodawanie punktów, 170 eats?, 172

Poleć książkę




Skorowidz

head-overlaps-body?, 172 lose?, 172 move, 171 point-to-screen-rect, 171 ruch wa, 171 sprawdzanie warunków zwycistwa, 172 turn, 173 tworzenie nowego jabka, 171 tworzenie wa, 171 tworzenie zestawu staych, 169 win?, 172 wykrywanie zetknicia, 172 zjadanie jabka, 172 zmiana kierunku wa, 173 model zmiennego stanu, 169, 173 reset-game, 173 update-direction, 174 update-positions, 174 wyduanie wa, 174 zmiany pozycji wa i jabka, 173 konstrukcje skadniowe, 24 liczba, 46 BigDecimal, 48 BigInt, 48 cakowita, 48 Ratio, 48 wektor, 47 zmiennoprzecinkowa, 48 lista, 46, 47 wywoywanie funkcji, 47 acuch znaków, 46, 49 wywoanie, 50 odwzorowania, 46, 52 sekwencje, 85 rekordy, 52 wywoywanie, 54 sowo kluczowe, 46, 53 symbol, 46, 49 warto logiczna, 46 reguy dziaania, 51 warto nil, 46 wektory, 46 sekwencje, 84

Kup książkę

305

zbiory, 46 sekwencje, 85 znak, 46

L Leiningen, 34, 261 pobieranie zalenoci, 35 wtyczka lein-noir, 287 leniwe sekwencje, 121, 125 moment realizacji, 127 Lisp, 15, 24

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

Poleć książkę


306



makra konstrukcje specjalne, 215 lazy-seq, 125 let, 221 letfn, 124 manipulowanie list, 210 ns, 67 obsuga kilku konstrukcji, 208 obsuga szablonów, 211 przechwytywanie symboli, 213 splicing unquote, 211 unquote, 211 przetwarzanie, 203 reguy stosowania, 202 reify, 198 rozwijanie, 206 rekurencyjne, 207 tworzenie, 212 sprawdzanie, 206 sterowanie przebiegiem programu, 202 tablice Javy, 260 taksonomia, 214 kategorie, 216 time, 212, 221 tworzenie, 203 tworzenie nazw, 212 nazwy lokalne, 214 tworzenie zmiennych, 218 unikanie funkcji anonimowych, 223 unless, 203 upraszczanie, 209 wartociowanie argumentów, 203, 206 nakadki, 221 odraczanie, 220 warunkowe, 216 when, 208 when-not, 202, 208 with-open, 221, 245 with-out-str, 221 wspódziaanie z Jav, 219 wzorzec projektowy, 205 makra odczytu, 55 dereferencja, 56

Kup książkę

Programowanie w jzyku Clojure

funkcja anonimowa, 56 komentarz, 55, 56 metadane, 56 podawanie zmiennych, 56 przytaczanie, 56 syntax-quote, 56 unquote, 56 unquote-slicing, 56 wzorzec wyraenia regularnego, 56 maszyny JVM, 15, 29 autorekurencja, 124 Clojure, 16 Java, 16 memoizacja, 165 metadane, 77 standardowe klucze, 78 model czasu, 24

N niezmienne struktury danych, 27

O optymalizacja TCO, 73, 123

P pami STM, 32, 151 technika MVCC, 153 transakcje, 151 ACI, 151 aktualizacje, 151 polimorfizm, 231 programowa pami transakcyjna, Patrz pami STM programowanie, 16, 18, 31, 97, 148 funkcyjne, 18, 24, 30, 116 autorekurencja, 124 czyste funkcje, 116 definicje rekurencyjne, 121 leniwe podejcie, 118, 121 leniwe sekwencje, 121, 125 problemy rekurencyjne, 138 prosta rekurencja, 122

Poleć książkę




Skorowidz

reguy, 120 rekurencja, 118 rekurencja kocowa, 123 rekurencja wzajemna, 136 trwae struktury danych, 117 wielokrotne wykorzystanie kodu, 119 wspóuytkowanie struktur, 117 wyraenie listowe, 31 zalety, 119 imperatywne, 31 kod ptli, 74 prawidowy proces pisania kodu, 273 sekwencyjne, 97 testowanie kodu, 274 BDD, 286 generowanie danych testu, 279 podstawowe etapy, 278 programowe sprawdzanie poprawnoci, 280 przeprowadzanie testów, 276, 283 sprawdzanie poprawnoci danych wyjciowych, 277 sprawdzanie poprawnoci kodu, 278 TDD, 286 testy jednostkowe, 286 testy regresji, 277 tworzenie danych wejciowych, 275 zgaszanie bdu, 284 wspóbiene, 148 powody stosowania, 148 wykorzystanie abstrakcji, 180 obsuga dodatkowych typów, 181 odczyt, 180 zapis, 180 protokoy, 24, 179, 184 zalety, 184 przestrze nazw, 36, 65 clojure.core, 66 clojure.string, 67 funkcje, 68 modyfikacja deklaracji, 264 myapp, 66 user, 36, 65 wizania, 65

Kup książkę

307

R referencje, 150 sprawdzanie poprawnoci, 156 transakcje, 150 ACID, 151 aktualizowanie informacji, 152 atomowe, 151 izolowane, 151 licznik, 155 pami STM, 151 skoordynowane, 151 spójne, 151 trwae, 151 warto wewntrztransakcyjna, 153 waciwoci, 151 zmiana encji, 150 tworzenie, 150 rekordy, 193 dodawanie metod, 195 dostp do pól, 194 implementacja protokou, 195 Note, 193 odwzorowania, 193 Person, 26 tworzenie, 193 rekurencja, 72, 118 autorekurencja, 124 definicje, 121 indukcja, 121 przypadek bazowy, 121 problemy rekurencyjne, 138 prosta rekurencja, 122 przyspieszanie, 143 rekurencja kocowa, 123 optymalizacja TCO, 123 rekurencja wzajemna, 136 memoizacja, 144 optymalizowanie, 139 przeksztacanie na autorekurencj, 138 zastpowanie leniwym podejciem, 141

Poleć książkę


308



Programowanie w jzyku Clojure

S sekwencje, 29, 81 biblioteka, 86, 87 funkcje, 88 cechy, 83 filtrowanie, 91 funkcje, 91 funkcje, 83 into, 86 Java, 98 kolekcje sekwencyjne, 82, 98 niezmienne, 87 odwzorowania, 85 predykaty, 92 przeksztacanie, 93 funkcje, 93 strumienie, 102 system plików, 101 funkcje, 101 tryb leniwy, 86, 96 stosowanie, 97 zalety, 96 tworzenie, 88 funkcje, 88 wektory, 84 wymuszanie realizacji, 97 wyraenia regularne, 100 funkcje, 100 zbiory, 85 stan, 147 agenty, 147, 158 bieca warto, 159 sprawdzanie poprawnoci, 160 transakcje, 161 tworzenie, 158 wykrywanie bdów, 160 atomy, 147, 157 dereferencja, 157 tworzenie, 157 ustawienie wartoci, 157 model aktualizacji, 163 modele zarzdzania, 168

Kup książkę

referencje, 147, 150 transakcje, 150 tworzenie, 150 wywoywane zwrotnie metody, 166 zmienne, 147, 163

rodowisko REPL, 35 zmienne specjalne, 36

T tworzenie aplikacji, 269 instalowanie kodu, 292 git push, 292, 294 Heroku, 292 plik Procfile, 292 testowanie kodu wyniku, 274 defspec, 282 dir, 279 failures, 284 generate-test-data, 282 generowanie danych testu, 279 in-ns, 281 programowe sprawdzanie poprawnoci, 280 random-secret, 280 require, 279 score print-table, 276 score-inputs, 278 selections, 275 sprawdzanie poprawnoci danych wyjciowych, 277 test dla danych wejciowych, 276 test-dirs, 283 test-namespaces, 283 test-vars, 283 testy regresji, 277 tworzenie danych wejciowych, 275 zgaszanie bdu, 284 tworzenie interfejsu, 287 board, 290 defpartial, 288 dodanie stanu, 287

Poleć książkę




Skorowidz

framework sieciowy, 287 interfejs gracza, 288 render, 290 session/flash-put!, 290 session/get, 287 session/put!, 287 session/remove!, 290 wynik, 270 exact-matches, 271 frequencies, 271 generowanie, 270 merge-with, 272 score, 273 select-keys, 272 unordered-matches, 272 typy danych, 179, 188 anonimowe egzemplarze, 198 cechy, 188 CryptoVault, 179, 188 definiowanie metod, 189 dostp do pól, 189 rekordy, 193 tworzenie, 189 typy referencyjne, 38 atom, 38

W wizania, 62 bindings, 63 dynamiczne, 164 modyfikacje na odlego, 164 dynamicznie okrelany zasig, 164 funkcje, 62 zasig leksykalny, 63 lokalne, 164 mechanizm rozkadania struktury, 63 podstawowe, 61 przestrze nazw, 65 zmienne, 62

Kup książkę

309

wielometody, 225 account-level, 235 assert-expr, 240 definiowanie, 228 dodawanie implementacji metod, 228 domylne dziaanie, 230 dora ne taksonomie, 233 dziedziczenie, 236 mechanizm wybierania implementacji, 229 my-print, 228, 231 paint, 175 service-charge, 235 stosowanie, 237 reguy, 241 wybieranie metod, 229 dla typu kolekcji, 231 na podstawie typu pierwszego argumentu, 231 rozwizywanie konfliktów, 232 wspóbieno, 32 wyraenie listowe, 94 elementy, 94

Z zmienne, 36, 61, 163 aliasy, 62 cechy, 62 mechanizm rozkadania struktury, 63 metadane, 62 rodzaje definicji, 133 specjalne, 164 modyfikacje na odlego, 164 tworzenie, 133 makra, 218 wizania, 62 lokalne dla wtku, 164 podstawowe, 61

Poleć książkę


310



Kup książkę

Programowanie w jzyku Clojure

Poleć książkę


Programowanie w j zyku Clojure  
Read more
Read more
Similar to
Popular now
Just for you