13 listopada 2009

Funkcyjne wyjście z REPL z (exit) i ankieta językowa

Już dawno nie czułem takiej radości z tak niewielkiej ilości kodu. Chyba wciąż jestem przerażony liczbą nawiasów w Clojure, więc kiedy napisałem funkcję (exit) bezbłędnie za pierwszym razem, można sobie wyobrazić, jaki byłem szczęśliwy.
 user=> (def exit (fn [] (. System exit 0)))
#'user/exit
user=> (exit)
Brakowało mi tej funkcji w Clojure REPL, bo ^C, czy ^Z + ENTER pachniały mi jakąś niedoróbką. W tak niewielkiej funkcji udało mi się wykorzystać 3 istotne możliwości Clojure - definiowanie zmiennej przez def, której przypisano funkcję anonimową przez fn, która z kolei wykorzystuje integrację Clojure z Javą za pomocą specjalnej formy . (kropka). Ale ze mnie programista, co? :)

Można to jednak lekko podrasować i wykorzystać specjalną formę #(), która również definiuje funkcję anonimową. Owa funkcja anonimowa w niektórych kręgach nazywana jest...domknięciem (ang. closure). Domknięcie w Clojure nie różni się bardzo w porównaniu do tradycyjnego wywołania funkcji, ale tym razem owe wywołanie fn kończy się stworzeniem nowej. Funkcja, która operuje na innych, w tym zwraca je, nazywamy funkcją wyższego poziomu (ang. higher-order function).

Wracając do naszego #() to możnaby powyższe zapisać tak:
 user=> (def exit #(. System exit 0))
#'user/exit
user=> (exit)
Przeglądając kod źródłowy "Game of Life" Scotta Frasera trafiłem na metodę java.lang.Runtime.availableProcessors(), o której istnieniu nie wiedziałem. W zasadzie o wielu metodach jeszcze nie wiem i wiele z nich wywrze na mnie podobne, pozytywne wrażenie, aczkolwiek ta ma tą zaletę, że utwierdziła mnie w przekonaniu, że mój laptop faktycznie posiada procesor 2-rdzeniowy i 2 wątki powinny działać równolegle (biorąc pod uwagę działanie wszystkich innych programów w tle, pewnie tak nie będzie i jeden z wątków i tak będzie szybszy).
 user=> (def available-procs (.. java.lang.Runtime getRuntime availableProcessors))
#'user/available-procs
user=> (println available-procs)
2
nil
Zadanie dla wytrwałych: Jak zmienić def powyżej, aby możliwe było wykonanie (available-procs), który zwróci 2, tj.
 user=> (available-procs)
2
p.s. Rozpocząłem kolejną ankietę odnośnie języków programowania "Jaki język programowania używasz poza Javą?" (jest na blogu po prawej u góry). Nie ma znaczenia, czy do zabawy, w projekcie, własnej ciekawości, czytasz o nim książkę, czy podobnie. Poświęcasz swój czas, więc wystarczy, aby określić go jako "używasz". Interesuje mnie, czy chociażby rozważasz alternatywę dla Javy i jaki to jest język. Wszystkie języki poza JVM wpadły do kategorii "Inne (poza JVM)". Głosujcie!