Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00243 004379 15026807 na godz. na dobę w sumie
Programowanie w języku Clojure - książka
Programowanie w języku Clojure - książka
Autor: , Liczba stron: 312
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-246-5372-0 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> inne - programowanie
Porównaj ceny (książka, ebook, audiobook).

Przewodnik po Clojure dla każdego!

Clojure to jeden z najciekawszych współczesnych języków programowania funkcyjnego. Jest obecny na rynku od pięciu lat. Język jest oparty o wirtualną maszynę języka Java i zachęca użytkowników do programowania współbieżnego. W ostatnim czasie Clojure gwałtownie zdobywa popularność i uznanie wśród programistów. Dzieje się tak, ponieważ jest dobrze przemyślany i wspaniale zaprojektowany, kryje w sobie potencjał języka Lisp, a do tego jest szybki i działa na dobrze znanej wszystkim wirtualnej maszynie.

Ta książka to kompletny przewodnik po Clojure. Lekturę zaczniesz od poznania jego zalet, składni i zasad programowania. W momencie, kiedy zbudujesz solidne fundamenty, przejdziesz do nauki programowania funkcyjnego, które wymaga pewnej zmiany w sposobie myślenia. Ale nie martw się, z tą książką przyjdzie Ci to z łatwością! W kolejnych rozdziałach skupisz się na programowaniu współbieżnym, protokołach, typach danych i makrach. Zobaczysz również, jak za pomocą Clojure stworzyć klasę języka Java, oraz zaznajomisz się z procesem tworzenia kompletnej aplikacji korzystającej z Clojure. Jeżeli chcesz poszerzyć swoje horyzonty programistyczne, trafiłeś na idealną książkę. Ta inwestycja się opłaci!

Poznaj zalety Clojure:

Zmień myślenie na funkcyjne!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

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 treĂci PodziÚkowania ............................................................................................10 Przedmowa do wydania drugiego .............................................................11 Przedmowa do wydania pierwszego ........................................................13 WstÚp ...........................................................................................................15 Rozdziaï 1. Wprowadzenie .........................................................................23 1.1. Dlaczego Clojure? .............................................................................................24 1.2. Szybkie wprowadzenie do programowania w Clojure ...........................................34 1.3. Biblioteki jÚzyka Clojure .....................................................................................40 1.4. Podsumowanie ..................................................................................................44 Rozdziaï 2. PrzeglÈd jÚzyka Clojure ..........................................................45 2.1. Konstrukcje skïadniowe ......................................................................................46 2.2. Makra odczytu ...................................................................................................55 2.3. Funkcje .............................................................................................................56 2.4. Zmienne, 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 8  Programowanie w jÚzyku Clojure Rozdziaï 3. Ujednolicanie danych za pomocÈ sekwencji .......................81 3.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 ...................................................115 4.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 .........................................................................................147 5.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 .......................................................179 6.1. Programowanie z wykorzystaniem abstrakcji ......................................................180 6.2. Interfejsy .........................................................................................................183 6.3. Protokoïy ........................................................................................................184 6.4. Typy danych ...................................................................................................188 6.5. Rekordy ..........................................................................................................193 6.6. Makro reify .....................................................................................................198 6.7. Podsumowanie ................................................................................................199 Spis treĂci  9 Rozdziaï 7. Makra .....................................................................................201 7.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 ..........................................................................225 8.1. ¿ycie bez wielometod ......................................................................................226 8.2. Definiowanie wielometod .................................................................................228 8.3. WiÚcej niĝ proste wybieranie metod ...................................................................231 8.4. Tworzenie doraěnych taksonomii ......................................................................233 8.5. Kiedy naleĝy korzystaÊ z wielometod? ...............................................................237 8.6. Podsumowanie ................................................................................................241 Rozdziaï 9. Sztuczki z JavÈ ......................................................................243 9.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 ............................................................269 10.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 22  Programowanie w jÚzyku Clojure Rozdziaï 1. Wprowadzenie S 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Ú. 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). 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 elegancki W 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. 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 wyraěniejsze 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/foo foo - #:user.Person{:first-name Aaron , :last-name Bedra } 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 Lisp Clojure 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: 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ĂÊ 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ów Clojure 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 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 funkcyjny Clojure 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 ) 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. 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ĝne Mechanizmy 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))) 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 Clojure Clojure 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). 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 wprowadzenie do 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 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ĝna zrobiÊ to w nastÚpujÈcy sposób: git clone git://github.com/clojure/clojure.git cd clojure mvn 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, dla któ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= : Clojure user= Teraz jesteĂ gotowy do wyĂwietlenia tekstu „Witaj, Ăwiecie”. Korzystanie ze Ărodowiska REPL Aby 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 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 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. 38  Programowanie w jÚzyku Clojure Dodawanie stanu wspóïuĝytkowanego Funkcja hello z poprzedniego przykïadu to czysta funkcja, czyli taka, której dziaïanie nie ma efektów ubocznych. Czyste funkcje ïatwo siÚ pisze i testuje. 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 } 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 sprawděmy, 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Ê. 40  Programowanie w jÚzyku Clojure 1.3. Biblioteki jÚzyka Clojure Kod jÚzyka Clojure jest umieszczony w bibliotekach. Kaĝda biblioteka jÚzyka Clojure znajduje siÚ w przestrzeni nazw, która jest odpowiednikiem pakietu Javy. BibliotekÚ jÚzyka Clojure moĝna 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. Rozdziaï 1. • Wprowadzenie  41 Instrukcje require i use Po 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”. 42  Programowanie w jÚzyku Clojure Znajdowanie dokumentacji Potrzebna 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, 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 wyjĂciowych funkcji doc obejmuje peïnÈ nazwÚ spraw- dzanej funkcji. W drugim znajdujÈ siÚ argumenty generowane bezpoĂrednio w kodzie. Wybrane czÚsto stosowane nazwy argumentów i ich zastosowanie omawiamy w ramce „Zwyczajowe nazwy parametrów”. Dalsze wiersze obejmujÈ ïañcuch znaków dokumentacji, jeĂli jest on podany w definicji funkcji. Zastosowanie Tablica Javy Agent Kolekcja Wyraĝenie Funkcja Indeks Referencja Wektor WartoĂÊ Zwyczajowe nazwy parametrów ’añcuchy 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 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 wtedy funkcjÚ, dlatego jest ona niedostÚpna, kiedy parametr znajduje siÚ w za- siÚgu programu. Dlatego nie naleĝy nazywaÊ referencji ref, agentów agent, a liczników — count, poniewaĝ sÈ to nazwy funkcji. 9 Tak naprawdÚ doc to makro jÚzyka Clojure. 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) 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. Podsumowanie Wï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. Skorowidz A agenty, 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 B biblioteki, 20, 40 dosïowne podawanie nazwy, 40 drzewo wïaĂciwoĂci systemowych, 238 znajdowanie dokumentacji, 42 C Clojure, 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 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 D definicja pustego ïañcucha znaków, 26 duck typing, 250 F funkcje, 56 anonimowe, 58 konstrukcja, 59 powody tworzenia, 58 stosowanie, 61 unikanie, 223 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 H hermetyzacja, 119 efekty uboczne, 120 Heroku, 292 biblioteka, 293 git init, 293 git push, 294 plik Procfile, 292 polecenie heroku, 293 rejestracja konta, 292 repozytorium git, 293 I instrukcje add-points, 171 agent-errors, 160 alias, 233 alter, 152 assoc, 171 atom, 157 binding, 164 clear-agent-errors, 160 commute, 154 concat, 210 cond, 227 condp, 182 conj, 38, 86 cons, 83, 132, 171 def, 38, 61, 218 defmacro, 203 defmethod, 228 defmulti, 175, 228 defn, 57 defonce, 133 defrecord, 27, 54 deref, 39, 150 derive, 236 dir, 279 do, 71, 219 doall, 97 dosync, 33, 150 faux-curry, 135 file-seq, 101 first, 76, 83 fn, 58 for, 75 force, 221 if, 70, 202 import, 67, 199 in-ns, 66, 281 inspect-tree, 238 304  Programowanie w jÚzyku Clojure instrukcje lazy-cat, 129 lazy-seq, 142 lein deps, 261 lein test, 40 let, 212 line-seq, 102 loop, 72 loop/recur, 72 macroexpand, 207 map, 219 memoize, 165 next-counter, 155 partial, 134 partition, 132 prefer-method, 232 println, 116, 203 project, 112 proxy, 176 pst, 37 recur, 72, 120, 130 ref, 156 refer, 41 ref-set, 150 require, 40, 41, 279 reset!, 157 rest, 83 score print-table, 276 select, 112 send, 159 send-off, 161 seq, 101, 258 set, 90 set!, 167, 254 source, 43 start, 163 swap!, 158 take-while, 91 trampoline, 139 unless, 202 use, 41, 66 var, 62 with-open, 102 J Java, 15, 16, 243 interfejsy, 183 wady, 183 zalety, 183 klasy BigDecimal, 249 BigInteger, 249 Character, 50 ChunkedSeq, 84 Person, 26 Random, 68 StringUtils, 74 Thread, 33 WidgetFactory, 205 metody egzemplarza, 204 obsïuga, 245 obsïuga wyjÈtków, 244 kontrolowane wyjÈtki, 244 porzÈdkowanie zasobów, 245 sekwencje, 98 kolekcje sekwencyjne, 98 wywoïywanie kodu, 68 K kod gry Snake, 169 interfejs GUI, 169, 175 aktualizowanie, 175 defmulti, 175 fill-point, 175 game, 176 game-panel, 175 paint, 175 proxy, 176 tworzenie nowej gry, 176 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 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 L Leiningen, 34, 261 pobieranie zaleĝnoĂci, 35 wtyczka lein-noir, 287 leniwe sekwencje, 121, 125 moment realizacji, 127 Lisp, 15, 24 M makra, 28, 201 amap, 260 and, 207, 216 areduce, 260 assert, 222 bad-unless, 207 bench, 212 binding, 164, 221 chain, 209 comment, 217 cond, 30 czas kompilacji, 203 czas rozwijania makra, 203 declare, 137, 218 definterface, 183 defpartial, 288 defprotocol, 185 defrecord, 28, 193 defstruct, 218 deftype, 189 delay, 220 dosync, 221 dotimes, 250 extend-protocol, 186 extend-type, 186 for, 95 import-static, 220 is, 239 jÚzyk szablonów, 210 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 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 podejĂcie, 118, 121 leniwe sekwencje, 121, 125 problemy rekurencyjne, 138 prosta rekurencja, 122 Skorowidz 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  307 R referencje, 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 308  Programowanie w jÚzyku Clojure S sekwencje, 29, 81 biblioteka, 86, 87 funkcje, 88 cechy, 83 filtrowanie, 91 funkcje, 91 funkcje, 83 into, 86 Java, 98 kolekcje sekwencyjne, 82, 98 niezmienne, 87 odwzorowania, 85 predykaty, 92 przeksztaïcanie, 93 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 funkcje, 93 strumienie, 102 system plików, 101 funkcje, 101 tryb leniwy, 86, 96 stosowanie, 97 zalety, 96 tworze
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Programowanie w języku Clojure
Autor:
,

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: