Clojure – Introduction

Skoro zdecydowaliśmy, że Clojure będzie naszym podstawowym językiem 1 to wypadało by go przedstawić.

Disclaimer:

Nie uważam się w żadnym stopniu za specjalistę od clojure, ani nie korzystałem z niego wcześniej. Wiedza na której oparte są poniższe zapiski wywodzi się z artykułów, prezentacji i wypowiedzi innych osób.

Tak więc, oto co możemy dowiedzieć się na temat clojure bez żadnego kodowania:

  • Dynamically typed
  • Open source
  • Functional
  • Lisp
  • Immutability
  • Works on certain runtime(s)
  • Maturity
  • Have goddamn half-life logo in its logo!

Dynamically typed

Ah, ta odwieczna walka typowań: statyczne – dynamiczne.
Co ciekawe, trwa ona już od dłuższego czasu (nie, nie od czasu JavaScriptu).
Pierwszy raz można było ją zaobserwować w okresie asymilacji C++ do grupy języków komercyjnych 2.

Ponieważ czyste C było quasi-dynamiczne 3 a C++ miał wymuszoną deklarację wszystkiego wszędzie (aby potem kompilator nie pozwalał na m.in. błędne wywołania), pierwszą linią obrony przeciwników C++ był argument:

W C++ to tyle dodatkowego kodu muszę naklepać aby cokolwiek zrobić, że głowa mała. Toż to marnotrawco czasu! O ile szybciej w C bym to napisał!

Oczywiście, powyższy argument mija się z prawdą dosyć pokaźnie, (bo wyszukiwanie błędów na runtime jest o wiele bardziej czasochłonne niż błędów kompilatora) jednakże coś w tym jest.

Statycznie typowane języki potrzebują więcej kodu, aby uzyskać tą samą funkcjonalność, niż języki dynamiczne.

Więcej kodu – nie czasu poświęconego na development. Zasadnicza różnica. Statyczne języki potrafią zaoszczędzić ów czas eliminując sporą cześć błędów już na etapie kompilacji.

Osobiście preferuje języki dynamiczne (większość błędów jakie potrafi znaleźć kompilator jestem w stanie zastąpić unit testami) – pracuje mi się przy nich po prostu o wiele szybciej.

No ale my tu nie o tym – trochę zszedłem z tematu.
Wróćmy zatem do clojure.

Open source

Jak dla mnie – spory plus. Możliwość podejrzenia implementacji konkretnych funkcji oraz wsparcie community – to tylko kilka rzeczy na które warto zwrócić uwagę.

Functional

Na temat programowania funkcjonalnego można pisać epopeje. Więc aby nie zanudzać to najważniejsze:

Functional programs do not have assignment statements, that is, the value of a variable in a functional program never changes once defined.

Tak, dla większości to dosyć zaskakujące jak można programować bez przypisywania i zmiennych, jednakże jest to jak najbardziej możliwe.
Ogólnie dzisiejszy trend powoli pełznie w stronę programowania funkcyjnego, chociaż nie tak szybko jak kiedyś sunął trend programowania obiektowego.

Osobiście – moje doświadczenia z programowanie funkcyjnym nie są za bardzo pokaźne. JavaScript, python, C# (Linq) zawierają jakąś formę takiego podeścia ale nie są ściśle na to nastawione jak np. Haskell. Jedyne co mogę dodać od siebie to, że kombinacja map+reduce oraz jej wykorzystanie bywa bardzo satysfakcjonujące 🙂

Lisp

Lisp jest często postrzegany jako rodzina języków programowania dla nadludzi. W sensie, że pozwala programować język programowania.

A tak na poważnie. Lisp traktuje kod źródłowy tak samo jak dane – co z kolei umożliwia tworzenie makr. Jeżeli w danym języku, brakuje jakieś funkcjonalności (na poziomie składni) to jedyną możliwością jaką mamy to poprosić autora o jej dodanie. W rodzinie Lisp mamy możliwość samemu ją sobie zaimplementować.

Dla przykładu:

W C# jakiś czas temu zostały dodane słowa kluczowe “async” i “await” które ułatwiły developerom programowanie asynchroniczne.

Ułatwienie polegało na zastąpieniu (w pseudokodzie):

bool isDone = false;

void Main()
{
	DoWorkAsync(Callback);
	while(!isDone){}
}

void Callback(int x)
{
	isDone = true;
	Console.WriteLine(x);
}

Tym:

async void Main()
{
	int x = await DoWorkAsync();
	Console.WriteLine(x);
}

Prawdopodobnie jesteś sobie w stanie podejrzewać jaki szacher-macher dzieje się pod spodem. Kompilator tnie Twój kod na pomniejsze funkcje i wywołuje je jak w przykładzie pierwszym (upraszam mocno). Zaiste, fajny feature. Ale czy aż taki skomplikowany?
Sęk w tym, że w językach z rodziny Lisp sam możesz sobie coś takiego napisać.

powerogskull

Yup, that’s awesome!

Immutability

Wszystkie podstawowe klocki z jakich budujemy program w clojure są niezmienne/stałe.
Z racji podejścia funkcjonalnego jest to dosyć oczywiste, jednakże clojure poszerza ten pomysł. Nie tylko nie możemy w nim przypisywać zmiennych (paradygmat funkcjonalny) jak i wszystkie struktury danych są całkowicie niezmienne. Np. przy dodaniu elementu do listy dostajemy nową listę zawierającą elementy z poprzedniej + nowo dodany.

Jest to jedna z tych “głośniejszych” funkcjonalności clojure – wsparcie w programowaniu wielowątkowym. W środowisku wielowątkowym największym problemem jest zmienny stan aplikacji – wymaga on synchronizacji wątków. W przypadku kiedy wszystko jest niezmienne/stałe – synchronizacja nie jest już wymagana. (znów mocno upraszczam)

Dodatkowo, jest to jedna z cech które były brane przy projektowaniu całego języka – zatem implementacja dba o odpowiednią wydajność w tej kwestii.

Works on certain runtime(s)

Jedna z ciekawszych rzeczy które nie są aż tak bardzo “sprzedawane” przez PR clojure’a.
Oryginalnie clojure działa na JVM – generuje kod zrozumiały dla maszyny wirtualniej javy.
JVM z kolei jest dostępny na całej masie sprzętu/systemów więc jest dobrym wyborem w kwestii multiplatformowości.

Tutaj możesz przypominać sobie tekst z poprzedniego posta.

Chciałbym aby mój silnik był dostępny w formie jar/dll/js.

Otóż okazuje się, że clojure został tak ciepło przyjęty, że istnieją jego implementacje zarówno w CLR jak i JavaScript.

ITcrowdApplause
Nice!

Domyślam się, że nie jest zmiana w formie jednego kliknięcia ale wciąż – potencjał jest naprawdę spory.

Maturity

Czy clojure jest już odpowiednio dojrzały? Moim zdaniem tak, w USA jest już całkiem popularnym rozwiązaniem. Korzystają z niego duże i znane firmy. O ile sam nie lubię suchych ankiet/wykresów to z podsumowaniami rocznymi warto się zapoznać: Clojure 2105

 

Ufff, trochę tego wyszło.
Zatem, pozostało nam tylko przygotować środowisko i zabrać się do pracy!

Know more:

  1. Od czasu do czasu będziemy również potrzebowali skorzystać z innych języków
  2. Czyli wykorzystywanych poza zakres akademicki
  3. Niezadeklarowane typy były traktowane jako integer a kompilator pozwalał na wywołanie funkcji z niezgodnymi argumentami

3 Comments

  1. 6 March 2016
    Reply

    Jestem pod wielkim wrażeniem ilości oraz jakości przekazanej przez Ciebie wiedzy! Świetnie wytłumaczyłeś podstawowe cechy języków funkcyjnych. Waiting for more 😉

  2. 12 April 2016
    Reply

    I’ll immediately grab your rss as I can not in finding your email subscription link or newsletter service.

    Do you’ve any? Please allow me know in order that I may just subscribe.
    Thanks.

Leave a Reply to Kill Cancel reply