Clojure
1 inlägg
• Sida 1 av 1
Clojure
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:
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):
Ett fönster till detta:
Så att
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:
och iterate: f n -> (n (f n) (f (f n) ...), som i:
En rekursivt definierad funktion som fibonaccitalen kan vi i Clojure uttrycka som en oändlig sekvens:
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:
Det finns stödmoduler för Clojure till bland annat Eclipse, Emacs och Vim.
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))
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.
Återgå till Intressanta intressen