(throw (BrowserTooLameException. "Chrome oder Firefox vonnöten"))
(ns de.sourcetalk.2012.clojure)
(def smartclaim
"Lisp's power is multiplied by the fact
that your competitors don't get it.
-- Paul Graham, Beating the Averages")
Source Talk Tage 2012
Stefan Kamphausen
Diese Präsentation verwendet:
"LISP is worth learning for a different reason - the profound enlightenment experience you will have when you finally get it. That experience will make you a better programmer for the rest of your days, [..]" -- Eric S. Raymond
lein repl und M-x nrepl oder M-x nrepl-jack-in
(defproject STT2012 "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "FIXME Eclipse Public License"
:url "FIXME"}
:dependencies [[org.clojure/clojure "1.4.0"]])
project.cljlein helplein sample zeigt eine ausführliche und dokumentierte
Projektdefinition
user=> 1
1
user=> 123
123
user=> 123.456
123.456
user=> :keyword
:keyword
source, doc, find-doc
(println "Hello World.")
'(println "Hello World.")
"Hello World."
(type "Hello World.") ;; ...
["ein" "vector" :von "dingen" 12 12.34 4/3]
{:kstring "value" :kkeyword :anothervalue
:kint 99 :kchar \s}
#{"ein" "Set" :von "Dingen" 123}
'(true false nil "eine Liste")
true, false, nil
entsprechen Boolean.True/False und nullget, nth, Keyword als Funktion, Datenstruktur als
Funktion
(defn einfache-funktion [arg1 arg2]
(println "Arg1:" arg1 "Arg2:" arg2))
(def quadrat (fn [x] (* x x )))
(defn fn-mit-destruct [[a1 a2]] [a2 a1])
(defn multi-arity-fn
([a1] (multi-arity-fn a1 "Default"))
([a1 a2] (vector a1 a2)))
(defn fn-mit-doc
"Dokumentation [...]"
[] (println "Hello World."))
defn; Makro: Eigentlich def
und fn
(let [pi (Math/PI)]
(Math/cos pi))
(new java.io.File "/etc")
(java.io.File. "/etc")
(.isFile (java.io.File. "/etc"))
(.nextFloat (java.util.Random.))
(java.net.URLEncoder/encode "Dick & Doof" "UTF-8")
(let [pi (Math/PI)]
(Math/cos pi))
new oder nur ..methodenName
(if (= 0 (+ 2 3))
"Math is broken"
"Puh, alles gut")
(cond
(= 0 (+ 2 3)) "Math is broken"
(= 5 (+ 2 3)) "Richtig"
(> 5 (+ 2 3)) "Auch richtig, aber...")
(condp = (class x)
String (.toLowerCase x)
Integer (str (Character/toLowerCase (char x))))
if: drei Argumente, Test, Then, Elsecond: Beliebig viele Paare aus Test und Thenand, or, docondp: Immer gleiches Prädikatcase, when, if-let,
when-let, cond-let, if-not,
when-not
Abstraktion: Erstes Element und Rest: first und rest
bzw. next
(let [s [1 2 3]]
[(first s) (second s) (nth s 2)])
[(first [1]) (next [1]) (rest [1])]
(let [v ["1" :zwei]]
[(cons 3 v) (conj v 3)])
(range 2 10)
(doseq [x [1 2 3] y [1 2 3]]
(println "x und y sind jetzt" x y))
first, second, nth(linear time)next und rest am Endecons oder conjdoseq
(defn seq-test [sq]
[(first sq) (rest sq) (cons 99 sq)])
(doseq [sq [[1 2] "abc" {:a 1, :b 2}
(java.util.ArrayList. [1 2])
(int-array 2 [4 5])]]
(println (seq-test sq)))
seq gewickelt
(map inc [1 2 3])
(map * (range 1 4) (range 10 100))
(map #(str "(" % ")") (range 10))
(map #(str "(" %1 "," %2 ")") (range 10) (range 5))
(map (fn [[x y]] (* x y))
(map vector (range 1 5) (range 5 10)))
#() oder fn#(): %
oder %1...%9amap auch für Arrays (Performance...)
(take 5 (iterate inc 0))
(nth (map #(* % %) (iterate inc 0)) 100)
(def abc (map (fn [x] (printf "<%d> " x) (* 2 x))
(range 100)))
(take 2 abc)
takedoall, Seiteneffekte: dorunabc mit doall und dorun durchführen.
dorun und map? doseq!
(reduce + (range 101))
(reduce str (range 10))
(def x ["ich" "und" "du" "muellers" "esel"
"meiers" "kuh"])
(reduce (fn [acc v] (str acc " " v)) x)
(reductions #(str %1 " " %2) x)
(reductions str "startwert" "SEQ")
reductions zeigt einzelne Schritteareduce auch für Arraysreduce Minimum und Maximum einer Seq von
100 Zufallszahlen zwischen 0 und 100.
(filter #{2 3} (range -5 5))
(sort < [1 4 2 66 43 3 6 7 43 88])
(take-while #(< (count %) 2) ["a" "b" "abc"])
(let [v [1 2 3 4]]
[(partition 2 v) (partition 2 (next v))
(partition 2 1 v)])
(get (into {} (System/getProperties)) "os.name")
pos?sort-bytake-while, drop-while, split-with,
split-atintoconcat, cycle, distinct,
every?, not-any?, not-every?, interleave,
interpose,
Heuristik: finde die erste Stelle, an der sich 10 Sample hintereinander nur um 10 unterscheiden.
Neues Projekt anlegen; Rohdaten liegen bereits vor
sox -q orig.flac -t raw -c 1 -b 16 -e signed-integer -r 44100 - remix 1 \
> audio.raw
partition, with-open,
Arraybit-*-Funktionenapply nützlich?:use, :import
(ns workshop.audio
(:use [clojure.java.io :only [input-stream]])
(:import [java.io File]))
(defn get-raw-samples [file]
(let [buf (byte-array (.length (File. file)))]
;; was ist hier ungewoehnlich?
(with-open [is (input-stream file)]
(.read is buf))
(map (fn [[a b]]
(bit-or (bit-and a 0xff)
(bit-shift-left b 8)))
(partition 2 buf))))
(defn sample-to-second
([sample] (sample-to-second sample 44100))
([sample rate] (float (* sample (/ 1 rate)))))
prj/workshop.audiolein uberjar und -main ...
(defn analyze-file
([file] (analyze-file file 10 10))
([file width maxdiff]
(if-let [[values sample]
(first
(drop-while
#(> (- (apply max (first %))
(apply min (first %)))
maxdiff)
(map vector
(partition
width 1 (get-raw-samples file))
(iterate inc 0))))]
(format "%s: %fsec (%d@%d)" file
(sample-to-second sample)
(first values) sample)
(str file ":OK"))))
"Ich bin ein String-Literal: ein Wert"
[:das :ist :ein :Vector :von :Keywords]
2001 ; Eine Zahl. Ein Jahr? Ein Filmtitel?
(def gruendungsjahr-fsfe 2001)
(def einfuehrungsjahr-11-punkte-saetze 2001)
(def identitaet "def verknuepft Wert und Identität")
def erzeugt eine Var, mit Thread-lokalem Verhalten
| Typ | Kontext | Koordination | Ausführung |
|---|---|---|---|
| Var | lokal | eine Identität | synchron |
| Atom | übergreifend | eine Identität | synchron |
| Ref | übergreifend | mehrere Identitäten | synchron |
| Agent | übergreifend | eine Identität | asynchron |
(def atm (atom "Eins"))
(deref atm)
(swap! atm (constantly 1))
@atm
atomderef oder @ (Read-Syntax)(swap! ATOM FN); keine
Seiteneffekte!java.util.concurrent.atomic.AtomicReference
(.start (Thread. #(+ 2 3)))
(defn th-info []
(let [t (Thread/currentThread)]
{:Name (.getName t) :ID (.getId t)}))
(def fu (future (th-info)))
@fu
(doto (Thread. #(println th-info))
(.setName "Ich, Thread")
(.start)) ;; output in REPL/terminal
dotojava.util.concurrent.Executors
(def eine-ref (ref 1))
(dosync (alter eine-ref inc))
(deref eine-ref)
(dosync (alter eine-ref + 5))
ref, alter, derefdosyncalter gehen an Update-Funktioninc, decdotimes
(def kollisionen (atom 0))
(def hochzaehler (ref 0))
(def runterzaehler (ref 100))
(defn inc-mit-zaehl [value]
(swap! kollisionen inc)
(inc value))
(defn dec-mit-zaehl [value]
(swap! kollisionen inc)
(dec value))
(defn stm-funktion []
(dosync
(alter hochzaehler inc-mit-zaehl)
(alter runterzaehler dec-mit-zaehl)))
(dotimes [_ 100]
(.start (new Thread stm-funktion)))
[@hochzaehler @runterzaehler @kollisionen]
Schöner mit lokalen Variablenbindungen
(defn ref-praxis [n]
(let [koll (atom 0)
hochz (ref 0)
runterz (ref n)
inc-z (fn [val]
(swap! koll inc)
(inc val))
dec-z (fn [val]
(swap! koll inc)
(dec val))
stm-fn (fn []
(dosync
(alter hochz inc-z)
(alter runterz dec-z)))]
(dotimes [_ n]
(.start (new Thread stm-fn)))
(Thread/sleep 1000)
[@hochz @runterz @koll]))
LockingTransaction.java, Ref.java sowie
Agentsfinal static AtomicLong: Absoluter Zähler für readPoints, commitPoints
(def ag (agent "0"))
(dotimes [i 5]
(.start (Thread. #(send ag str " " i))))
send Berechnung auf fixem Thread-Poolsend-off wachsender Thread-Pool, z.B. I/O*agent*
(import [java.awt.event ActionListener]
[javax.swing JFrame JButton])
(doto (JFrame.)
(.add (doto (JButton. "Picard")
(.addActionListener
(proxy [ActionListener] []
(actionPerformed [e]
(println "Energie!"))))))
(.pack)
(.setVisible true))
proxy
+---------------------+---------------------+---------+
| Markt | Alle Händler | Zustand |
+----------+----------+-----------+---------+---------+
| Symbol | Anzahl | Händler | Anz ges | Fehler |
+----------+----------+-----------+---------+---------+
| ... | ... | ... | ... | ... |
+----------+----------+-----------+---------+---------+
Siehe https://github.com/daveray/seesaw
seesaw.core :as s, seesaw.table :as t,
seesaw.timer :as stt/table-model, s/table, s/config!s/scrollable, s/vertical-panel,
s/label, s/left-right-splits/frame, st/timer, s/listen:id, s/select
