вторник, 7 юли 2009 г.

Clojure

Обичам лисп. Още веднага след като изгледах първите лекции от SICP серията, осъзнах че обичам функционалното програмиране, и обичам lisp езиците, и в частност scheme. Елегантноста на минималистичния синтаксис, мощните абстракции, простотата с която могат да се изразяват сложни идеи, това всичкото в един невероятно малък език. Scheme може да се научи буквално за часове, Scheme е единствения език който заслужава книга "Learn Scheme in N days", всички други подобни заглавия вероятно ви булшитват, тъй като е невъзможно да научиш php да речем за N часове. Всъщност наистина ИМА книга ма scheme наречена Teach Yourself Scheme in Fixnum Days, като до колкото разбрах fixnum е малко цяло число(или нещо от сорта). Книгата е САМО 100 страници, това са 50 листа!

След като обичам лисп и обичам функционалното програмиране, нормално е да се опитам да пиша програми на scheme, така и направих, поне за кратко. Така и не успях да напиша нищо особено дълго или впечатляващо. Но scheme си изигра ролята, заедно със гореспоменатите лекции, овладях основите на функционалното програмиране, разбрах как работят абстракциите, научих се как да създавам рекурсивни алгоритми, разбрах да разграничавам абстрактния модел по който работи дадена програма от реалния начин на работа(за да мога да разбирам по големи и сложни програми) и се научих да гледам на кода от високо, да мисля по абстрактно. Не е зле за език който научих за 1 седмица. След всичко това, така и не получих това което исках, малък език на който да програмирам бързо и лесно. Scheme е удобен език за обучение, но ако искаш да го ползваш "In real life"TM трябва да си наистина посветен на идеята. Няма да влизам в детайли относно това какво точно ме отказа от scheme, но като цяло леснотата с която писах код на Python(първия ми език), така и не беше достигната от scheme, което беше разочароващо.

От известно време се интересувах от clojure, диалект на lisp създаден специално за jvm-а предназначен за паралелно програмиране. Езикът има повечето предимства на традиционните лисп диалекти, но скъсва връзките с някой исторически остатъци, които са в ядрото на "старите лисп-ове", или поне така казват всички в нета :D Езикът набира популярност, но въпреки че отдавна го следя, едва на скоро имах време да го науча. Scheme опитът ми беше полезен, тъй като аз напрактика вече знаех по голямата част от езика, не ми отне повече от седмица да овладея основите.

Няма да обяснявам в подробности какво точно прави следния код, просто го поствам за да видите как изглежда Clojure по принцип:
(defn sort-banknotes [sum]
(loop [sum sum banknotes [50 20 10 5 2 1] sorted []]
(if (or (= sum 0)
(= (count banknotes) 0))
sorted
(recur
(mod sum (first banknotes))
(rest banknotes)
(conj sorted (int (/ sum (first banknotes))))))))

(println (sort-banknotes 394))


Кодът е прост, ето какво прави на бързо: разполагайки с банкноти от по 50,20,10,5,2 и 1 лв., за произволна сума трябва да се определи по колко банкноти от всеки номинал са необходими, като се предпочитат по едрите банкноти. Ето еквивалентната програма в c++ за сравнение:



#include<iostream>
using namespace std;

int bn[6]={50,20,10,5,2,1};
int sbn[6];
int sum;
int i;
int main(){
cout<<"summa za izchislenie=";
cin>>sum;
for(i=0;i<6;i++){
sbn[i]=sum/bn[i];
sum=sum%bn[i];
cout<<bn[i]<<"=>"<<sbn[i]<<endl;
}
}

В следващия ми пост ще говоря за Compojure, лека web framework за clojure, очаква се да е по интересно, ще има повече код поне :D