Clojure

Berätta om dina specialintressen och lär dig om andras.

 Moderatorer: Alien, atoms

Clojure

Inläggav Trolsk » 2009-11-09 22:29:32

Clojure är ett nytt språk och en modern implementation av Lisp för JVM. Det har direkt tillgång till hela javalib och är särskilt riktad mot multitrådad programmering. Clojure står på på funktionell programmering över immutable data, för att undvika låsningar trådar emellan; i stället implementeras en STM.

Lisp har en uniform prefix-syntax strukturerad i listor av listor; alltså träd. Några exempel:
Kod: Markera allt
(+ 1 1) => 2
(* (+ 1 2) (+ 4 5)) => 27
(apply str (reverse "Hello, world!")) => "!dlrow ,olleH"
.

Clojure har direkt tillgång till Java. Objekt av olika klasser kan instantieras samtidigt som dess metoder definieras. Denna metod anropas med valfri rendreringsfunktion, och ger en JPanel med överriden Jpanel.paint(graphics):

Kod: Markera allt
; (graphics -> nil) -> javax.swing.JPanel
(defn panel [render-fn]
  (proxy [JPanel] []
    (paint [g] (render-fn g))))


Ett fönster till detta:

Kod: Markera allt
; (graphics -> nil) -> javax.swing.JFrame
(defn frame-with-panel [render-fn]
  (doto (new JFrame)
    (.setContentPane (panel render-fn))
    (.show)))


Så att
Kod: Markera allt
(frame-with-panel (view-scene scene1))
skapar ett fönster med en specifik vy, vilket nyttjar en vanlig abstraktion i funktionell programmering: view-scene tar en scen och ger en funktion som tar en graphics: view-scene: scene -> (graphics -> nil): en delvis specifiering av en funktion.

Clojure implementerar lata sekvenser. Att en sekvens är lat innebär att nästa element inte är utvärderad. Elementen utvärderas inte förrän de behövs. Med detta kan vi definiera oändliga sekvenser ur vilka vi bara är intresserade av delar utav, med vilka vi kan iterera över godtyckligt genererade datamängder. Standarden ger exempelvis funktionen repeat: n -> (n n n ...), vilken vi kan tillämpa:
Kod: Markera allt
(take 3 (repeat 1)) => (1 1 1)

och iterate: f n -> (n (f n) (f (f n) ...), som i:
Kod: Markera allt
(take 3 (iterate inc 1)) => (1 2 3)


En rekursivt definierad funktion som fibonaccitalen kan vi i Clojure uttrycka som en oändlig sekvens:

Kod: Markera allt
; number-a number-b -> ((+ a b) + (fib-seq (+ a b) b))
(defn fib-seq [a b]
 (cons (+ a b) (lazy-seq (fib-seq (+ a b) a))))

=> (take 5 (fib-seq 1 1))
(2 3 5 8 13)


Lata sekvenser utvärderas till konstanter: referenserna till elementen utvärderas bara en gång. Vi kan därmed memoisera sekvenser genom att hålla en referens:

Kod: Markera allt
(def fibs (concat [1 1] (fib-seq 1 1)))

Vid bruk märks alltså skillnaden:

=> (time (dorun (take 100000 fibs)))
"Elapsed time: 4829.036374 msecs"

=> (time (dorun (take 10100 fibs)))
"Elapsed time: 218.992161 msecs


Det finns stödmoduler för Clojure till bland annat Eclipse, Emacs och Vim.
Trolsk
 
Inlägg: 347
Anslöt: 2007-07-04

Återgå till Intressanta intressen



Logga in