mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-23 09:41:36 +00:00
[clojure/de] Translate clojure (#3711)
This commit is contained in:
parent
ef6f8dd275
commit
5d9be7080d
422
de-de/clojure-de.html.markdown
Normal file
422
de-de/clojure-de.html.markdown
Normal file
@ -0,0 +1,422 @@
|
||||
---
|
||||
language: clojure
|
||||
filename: learnclojure-de.clj
|
||||
contributors:
|
||||
- ["Adam Bard", "http://adambard.com/"]
|
||||
translators:
|
||||
- ["Dennis Keller", "https://github.com/denniskeller"]
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Clojure ist ein Lispdialekt, der für die Java Virtual Maschine entwickelt worden ist. Sie hat eine stärkere Betonung auf reine [funktionale Programmierung](https://en.wikipedia.org/wiki/Functional_programming) als Common Lisp. Jedoch besitzt sie je nach Bedarf mehrere [STM](https://en.wikipedia.org/wiki/Software_transactional_memory) Werkzeuge zur Handhabung von Zustand.
|
||||
|
||||
Diese Verknüpfung erlaubt es parallele Verarbeitung sehr einfach und häufig automatisch zu verarbeiten.
|
||||
|
||||
(Du brauchst die Clojure Version 1.2 oder neuer)
|
||||
|
||||
```clojure
|
||||
; Kommentare starten mit einem Semikolon.
|
||||
|
||||
; Clojure wird in "Forms" geschrieben, was nur Listen von Dingen
|
||||
; in Klammern sind, getrennt durch Leerzeichen.
|
||||
;
|
||||
; Der Clojure Leser nimmt an, dass das Erste, was aufgerufen wird
|
||||
; eine Funktion oder ein Makro ist, der Rest sind Argumente.
|
||||
|
||||
; Der erste Aufruf in einer Datei sollte ns sein, um den Namespacezu setzen.
|
||||
(ns learnclojure)
|
||||
|
||||
; Weitere einfache Beispiele:
|
||||
|
||||
; str erstellt einen String aus allen Argumenten
|
||||
(str "Hallo" " " "Welt") ; => "Hallo Welt"
|
||||
|
||||
; Mathe ist einfach
|
||||
(+ 1 1) ; => 2
|
||||
(- 2 1) ; => 1
|
||||
(* 1 2) ; => 2
|
||||
(/ 2 1) ; => 2
|
||||
|
||||
; Gleichheit ist =
|
||||
(= 1 1) ; => true
|
||||
(= 2 1) ; => false
|
||||
|
||||
; Du brauchst auch not für Logik
|
||||
(not true) ; => false
|
||||
|
||||
; Verschachtelte Forms funktionieren, wie erwartet
|
||||
(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
|
||||
|
||||
; Typen
|
||||
;;;;;;;;;;;;;
|
||||
|
||||
; Clojure verwendet Javas Objekt Typen für Booleans, Strings und Zahlen.
|
||||
; Verwende `class` um sie zu inszipieren.
|
||||
(class 1) ; Integer Literalte sind standardmäßig java.lang.Long
|
||||
(class 1.); Float Literale sind java.lang.Double
|
||||
(class ""); Strings sind immer in doppelten Anführungszeichen notiert und sind java.lang.String
|
||||
(class false) ; Booleans sind java.lang.Boolean
|
||||
(class nil); Der "null" Wert heißt nil
|
||||
|
||||
; Wenn du ein literale Liste aus Daten erzeugen willst, verwendest du ' um
|
||||
; zu verhindern dass es evaluiert wird
|
||||
'(+ 1 2) ; => (+ 1 2)
|
||||
; (Kurzform für (quote (+ 1 2)))
|
||||
|
||||
; Du kannst eine zitierte Liste evaluieren
|
||||
(eval '(+ 1 2)) ; => 3
|
||||
|
||||
; Kollektioenn & Sequenzen
|
||||
;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Listen sind Linked-Lists Datenstrukturen, während Vektoren arraybasierend sind.
|
||||
; Vektoren und Listen sind auch Java Klassen!
|
||||
(class [1 2 3]); => clojure.lang.PersistentVector
|
||||
(class '(1 2 3)); => clojure.lang.PersistentList
|
||||
|
||||
; Eine Liste würde nur als (1 2 3) geschrieben, aber wir müssen es zitieren
|
||||
; damit der Leser aufhört zu denken, es sei eine Funktion.
|
||||
; Außerdem ist (list 1 2 3) das Selbe, wie '(1 2 3)
|
||||
|
||||
; "Kollektioen" sind nur Gruppen von Daten
|
||||
; Listen und Vektoren sind Kolllektionen:
|
||||
(coll? '(1 2 3)) ; => true
|
||||
(coll? [1 2 3]) ; => true
|
||||
|
||||
; "Sequenzen" (seqs) sind abstrakte Beschreibungen von Listen von Daten.
|
||||
; Nur Listen sind seqs.
|
||||
(seq? '(1 2 3)) ; => true
|
||||
(seq? [1 2 3]) ; => false
|
||||
|
||||
; Ein seq muss nur einen Eintrittspunkt bereitstellen, wenn auf ihm zugegriffen wird.
|
||||
; Das heißt, dass seqs faul sein können -- Mit ihnen kann man unendliche Serien beschreiben.
|
||||
(range 4) ; => (0 1 2 3)
|
||||
(range) ; => (0 1 2 3 4 ...) (eine unendliche Serie)
|
||||
(take 4 (range)) ; (0 1 2 3)
|
||||
|
||||
; Verwende cons um ein Item zum Anfang einer Liste oder eines Vektors hinzuzufügen.
|
||||
(cons 4 [1 2 3]) ; => (4 1 2 3)
|
||||
(cons 4 '(1 2 3)) ; => (4 1 2 3)
|
||||
|
||||
; Conj fügt ein Item auf die effizienteste Weise zu einer Kollektion hinzu.
|
||||
; Für Listen fügt er sie an den Anfang hinzu. Für Vektoren fügt er sie an das Ende hinzu.
|
||||
(conj [1 2 3] 4) ; => [1 2 3 4]
|
||||
(conj '(1 2 3) 4) ; => (4 1 2 3)
|
||||
|
||||
; Verwende concat um Listen und Vektoren miteinander zu verbinden
|
||||
(concat [1 2] '(3 4)) ; => (1 2 3 4)
|
||||
|
||||
; Verwende filter, map um mit Kollektionen zu interagieren
|
||||
(map inc [1 2 3]) ; => (2 3 4)
|
||||
(filter even? [1 2 3]) ; => (2)
|
||||
|
||||
; Verwende reduce um sie zu reduzieren
|
||||
(reduce + [1 2 3 4])
|
||||
; = (+ (+ (+ 1 2) 3) 4)
|
||||
; => 10
|
||||
|
||||
; Reduce kann auch einen Initalwert als Argument verwenden
|
||||
(reduce conj [] '(3 2 1))
|
||||
; = (conj (conj (conj [] 3) 2) 1)
|
||||
; => [3 2 1]
|
||||
|
||||
; Funktionen
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Verwende fn um neue Funktionen zu erstellen. Eine Funktion gibt immer ihr
|
||||
; letztes Statement zurück.
|
||||
(fn [] "Hallo Welt") ; => fn
|
||||
|
||||
; (Du brauchst exta Klammern um sie aufzurufen)
|
||||
((fn [] "Hallo Welt")) ; => "Hallo Welt"
|
||||
|
||||
; Du kannst eine Variable mit def erstellen
|
||||
(def x 1)
|
||||
x ; => 1
|
||||
|
||||
; Weise eine Funktion einer Variable zu
|
||||
(def hello-world (fn [] "Hallo Welt"))
|
||||
(hello-world) ; => "Hallo Welt"
|
||||
|
||||
; Du kannst den Prozess verkürzen indem du defn verwendest
|
||||
(defn hello-world [] "Hallo Welt")
|
||||
|
||||
; [] ist die Liste der Argumente für die Funktion
|
||||
; The [] is the list of arguments for the function.
|
||||
(defn hello [name]
|
||||
(str "Hallo " name))
|
||||
(hello "Steve") ; => "Hallo Steve"
|
||||
|
||||
; Du kannst diese Kurzschreibweise verwenden um Funktionen zu erstellen:
|
||||
(def hello2 #(str "Hallo " %1))
|
||||
(hello2 "Julie") ; => "Hallo Julie"
|
||||
|
||||
; Du kannst auch multi-variadische Funktionen haben
|
||||
(defn hello3
|
||||
([] "Hallo Welt")
|
||||
([name] (str "Hallo " name)))
|
||||
(hello3 "Jake") ; => "Hallo Jake"
|
||||
(hello3) ; => "Hallo Welt"
|
||||
|
||||
; Funktionen können auch extra Argumente in einem seq für dich speichern
|
||||
(defn count-args [& args]
|
||||
(str "Du hast " (count args) " Argumente übergeben: " args))
|
||||
(count-args 1 2 3) ; => "Du hast 3 Argumente übergeben: (1 2 3)"
|
||||
|
||||
; Du kannst reguläre und gepackte Argumente mischen
|
||||
(defn hello-count [name & args]
|
||||
(str "Hallo " name ", Du hast " (count args) " extra Argumente übergeben"))
|
||||
(hello-count "Finn" 1 2 3)
|
||||
; => "Hallo Finn, Du hast 3 extra Argumente übergeben"
|
||||
|
||||
|
||||
; Maps
|
||||
;;;;;;;;;;
|
||||
|
||||
; Hash maps und Array maps teilen sich ein Interface. Hash maps haben eine schnellere Zugriffszeit,
|
||||
; aber behalten keine Schlüsselreihenfolge.
|
||||
(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
|
||||
(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap
|
||||
|
||||
; Arraymaps werden durch die meisten Operatioen automatisch zu Hashmaps,
|
||||
; sobald sie groß genug werden. Das heißt du musst dich nicht darum sorgen.
|
||||
|
||||
; Maps können einen beliebigen Hash-Typ als Schlüssel verwenden, in der Regel
|
||||
; sind jedoch Keywords am besten. Keywords sind wie Strings, jedoch besitzen sie
|
||||
; Performancevorteile
|
||||
(class :a) ; => clojure.lang.Keyword
|
||||
|
||||
(def stringmap {"a" 1, "b" 2, "c" 3})
|
||||
stringmap ; => {"a" 1, "b" 2, "c" 3}
|
||||
|
||||
(def keymap {:a 1, :b 2, :c 3})
|
||||
keymap ; => {:a 1, :c 3, :b 2}
|
||||
|
||||
; Übrigens werden Kommas als Leerzeichen behandelt und machen nichts.
|
||||
|
||||
; Rufe einen Wert von einer Map ab, indem du sie als Funktion aufrufst
|
||||
(stringmap "a") ; => 1
|
||||
(keymap :a) ; => 1
|
||||
|
||||
; Keywords können auch verwendet werden um ihren Wert aus der Map zu bekommen!
|
||||
(:b keymap) ; => 2
|
||||
|
||||
; Versuche es nicht mit Strings.
|
||||
;("a" stringmap)
|
||||
; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
|
||||
|
||||
; Das Abrufen eines nicht vorhandenen Keys gibt nil zurück
|
||||
(stringmap "d") ; => nil
|
||||
|
||||
; Verwende assoc um einen neuen Key zu einer Hash-map hinzuzufügen
|
||||
(def newkeymap (assoc keymap :d 4))
|
||||
newkeymap ; => {:a 1, :b 2, :c 3, :d 4}
|
||||
|
||||
; Aber denk daran, Clojure Typen sind unveränderlich!
|
||||
keymap ; => {:a 1, :b 2, :c 3}
|
||||
|
||||
; Verwende dissoc um Keys zu entfernen
|
||||
(dissoc keymap :a :b) ; => {:c 3}
|
||||
|
||||
; Sets
|
||||
;;;;;;
|
||||
|
||||
(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
|
||||
(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3}
|
||||
|
||||
; Füge ein Element mit conj hinzu
|
||||
(conj #{1 2 3} 4) ; => #{1 2 3 4}
|
||||
|
||||
; Entferne ein Element mit disj
|
||||
(disj #{1 2 3} 1) ; => #{2 3}
|
||||
|
||||
; Teste auf Existenz, indem du das Set als Funktion verwendest:
|
||||
(#{1 2 3} 1) ; => 1
|
||||
(#{1 2 3} 4) ; => nil
|
||||
|
||||
; Es gibt mehr Funktionen in dem clojure.sets Namespace.
|
||||
|
||||
; Nützliche Forms
|
||||
;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Logische Konstrukte in Clojure sind nur Makros und sie sehen, wie alles
|
||||
; andere aus
|
||||
(if false "a" "b") ; => "b"
|
||||
(if false "a") ; => nil
|
||||
|
||||
; Verwende let um temporäre Bindungen aufzubauen
|
||||
(let [a 1 b 2]
|
||||
(> a b)) ; => false
|
||||
|
||||
; Gruppiere Statements mit do zusammen
|
||||
; Group statements together with do
|
||||
(do
|
||||
(print "Hallo")
|
||||
"Welt") ; => "Welt" (prints "Hallo")
|
||||
|
||||
; Funktionen haben ein implizites do
|
||||
(defn print-and-say-hello [name]
|
||||
(print "Sage Hallo zu " name)
|
||||
(str "Hallo " name))
|
||||
(print-and-say-hello "Jeff") ;=> "Hallo Jeff" (prints "Sage Hallo zu Jeff")
|
||||
|
||||
; let macht das auch
|
||||
(let [name "Urkel"]
|
||||
(print "Sage Hallo zu " name)
|
||||
(str "Hallo " name)) ; => "Hallo Urkel" (prints "Sage Hallo zu Urkel")
|
||||
|
||||
|
||||
; Verwende die Threading Makros (-> and ->>) um Transformationen von
|
||||
; Daten deutlicher auszudrücken.
|
||||
|
||||
; Das "Thread-zuerst" Makro (->) fügt in jede Form das Ergebnis des
|
||||
; Vorherigen als erstes Argument (zweites Element) ein.
|
||||
(->
|
||||
{:a 1 :b 2}
|
||||
(assoc :c 3) ;=> (assoc {:a 1 :b 2} :c 3)
|
||||
(dissoc :b)) ;=> (dissoc (assoc {:a 1 :b 2} :c 3) :b)
|
||||
|
||||
; Dieser Ausdruck kann auch als so geschrieben werden:
|
||||
; (dissoc (assoc {:a 1 :b 2} :c 3) :b)
|
||||
; and evaluates to {:a 1 :c 3}
|
||||
|
||||
; Der Doppelpfeil macht das Selbe, aber er fügt das Ergebnis von jeder
|
||||
; Zeile an das Ende der Form, Das ist vor allem für Operationen auf
|
||||
; Kollektionen nützlich:
|
||||
(->>
|
||||
(range 10)
|
||||
(map inc) ;=> (map inc (range 10)
|
||||
(filter odd?) ;=> (filter odd? (map inc (range 10))
|
||||
(into [])) ;=> (into [] (filter odd? (map inc (range 10)))
|
||||
; Result: [1 3 5 7 9]
|
||||
|
||||
; Wenn du in einer Situation bist, in der du mehr Freiheit willst,
|
||||
; wohin du das Ergebnis vorheriger Datentransformationen in einem Ausruck
|
||||
; platzieren möchtest, kannst du das as-> Macro verwenden. Mit diesem Macro
|
||||
; kannst du einen speziellen Namen auf die Ausgabe einer Transformationen geben.
|
||||
; Du kannst es als Platzhalter in verketteten Ausdrücken verwenden:
|
||||
|
||||
(as-> [1 2 3] input
|
||||
(map inc input);=> Du kannst die letzte Ausgabe der Transformation in der letzten Position verwenden
|
||||
(nth input 2) ;=> und auch in der zweiten Position, im selben Ausdruck verwenden
|
||||
(conj [4 5 6] input [8 9 10])) ;=> oder auch in der Mitte!
|
||||
|
||||
|
||||
|
||||
; Module
|
||||
;;;;;;;;;;;;;;;
|
||||
|
||||
; Verwende "use" um alle Funktionen aus einem Modul zu bekommen
|
||||
(use 'clojure.set)
|
||||
|
||||
; Nun können wir set Operationen verwenden
|
||||
(intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
|
||||
(difference #{1 2 3} #{2 3 4}) ; => #{1}
|
||||
|
||||
; Du kannst auch auswählen nur ein Subset von Funktionen zu importieren
|
||||
(use '[clojure.set :only [intersection]])
|
||||
|
||||
; Verwende require um ein Modul zu importieren
|
||||
(require 'clojure.string)
|
||||
|
||||
; Verwende / um eine Funktion aus einem Modul aufzurufen
|
||||
; Hier verwenden wir das Modul clojure.string und die Funktion blank?
|
||||
(clojure.string/blank? "") ; => true
|
||||
|
||||
; Du kannst auch einem Modul einem kürzerern Namen beim Import geben
|
||||
(require '[clojure.string :as str])
|
||||
(str/replace "Das ist ein Test." #"[a-o]" str/upper-case) ; => "DAs IsT EIN TEsT."
|
||||
; (#"" bezeichnet einen regulären literalen Ausdruck)
|
||||
|
||||
; Du kannst require aus einem Namespace verwenden (auch use ist möglich, aber nicht zu empfehlen)
|
||||
; indem du :require verwendest.
|
||||
; Du brauchst keine Zitierzeichen für deine Module verwenden, wenn du
|
||||
; es auf diese Weise machst.
|
||||
(ns test
|
||||
(:require
|
||||
[clojure.string :as str]
|
||||
[clojure.set :as set]))
|
||||
|
||||
; Java
|
||||
;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Java hat eine riesige und nützliche Standardbibliothek,
|
||||
; du möchtest lernen wie man sie verwendet.
|
||||
|
||||
; Verwende import um ein Java modul zu laden.
|
||||
(import java.util.Date)
|
||||
|
||||
; Du kannst auch von einem ns importieren.
|
||||
(ns test
|
||||
(:import java.util.Date
|
||||
java.util.Calendar))
|
||||
|
||||
; Verwende den Klassennamen mit einem "." am Ende, um eine neue Instanz zu erstellen
|
||||
(Date.) ; <a date object>
|
||||
|
||||
; Verwende . um Methoden aufzurufen oder verwende die ".method" Abkürzung
|
||||
(. (Date.) getTime) ; <a timestamp>
|
||||
(.getTime (Date.)) ; Genau das Selbe
|
||||
|
||||
; Verwende / um statische Methoden aufzurufen
|
||||
(System/currentTimeMillis) ; <a timestamp> (system ist immer da)
|
||||
|
||||
; Verwende doto um mit veränderliche Klassen besser umzugehen
|
||||
(import java.util.Calendar)
|
||||
(doto (Calendar/getInstance)
|
||||
(.set 2000 1 1 0 0 0)
|
||||
.getTime) ; => A Date. set to 2000-01-01 00:00:00
|
||||
|
||||
; STM
|
||||
;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Software Transactional Memory ist der Mechanismus, den Clojure verwendet
|
||||
; um mit persistenten Zuständen umzugehen. Es gibt ein Paar Konstrukte in
|
||||
; Clojure die es verwenden.
|
||||
|
||||
; Ein Atom ist das Einfachste. Gebe es einen Initalwert
|
||||
(def my-atom (atom {}))
|
||||
|
||||
; Update ein Atom mit swap!.
|
||||
; swap! nimmt eine Funktion und ruft sie mit dem aktuellen Zustand des
|
||||
; Atoms auf und alle nachfolgenden Argumente als das Zweite
|
||||
(swap! my-atom assoc :a 1) ; Setzt my-atom zu dem Ergebnis von (assoc {} :a 1)
|
||||
(swap! my-atom assoc :b 2) ; Setzt my-atom zu dem Ergebnis von (assoc {:a 1} :b 2)
|
||||
|
||||
; Verwende '@' um das Atom zu dereferenzieren und den Wert zu bekommen
|
||||
my-atom ;=> Atom<#...> (Gibt das Atom Objekt zurück
|
||||
@my-atom ; => {:a 1 :b 2}
|
||||
|
||||
; Hier ist ein einfacher Zähler mit einem Atom
|
||||
(def counter (atom 0))
|
||||
(defn inc-counter []
|
||||
(swap! counter inc))
|
||||
|
||||
(inc-counter)
|
||||
(inc-counter)
|
||||
(inc-counter)
|
||||
(inc-counter)
|
||||
(inc-counter)
|
||||
|
||||
@counter ; => 5
|
||||
|
||||
; Andere STM Konstrukte sind refs und agents.
|
||||
; Refs: http://clojure.org/refs
|
||||
; Agents: http://clojure.org/agents
|
||||
```
|
||||
|
||||
### Weiterführende Literatur
|
||||
|
||||
Das ist alles andere als erschöpfend, aber hoffentlich ist es genug, um dich auf die Beine zu stellen.
|
||||
|
||||
Clojure.org hat eine Menge von Artikeln:
|
||||
[http://clojure.org/](http://clojure.org/)
|
||||
|
||||
Clojuredocs.org hat eine Dokumentation mit Beispielen für die meisten Kernfunktionen
|
||||
[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core)
|
||||
|
||||
4Clojure ist eine gute Möglichkeit um deine clojure/FP zu verbessern:
|
||||
[http://www.4clojure.com/](http://www.4clojure.com/)
|
||||
|
||||
Clojure-doc.org (ja, wirklich) hat eine Reihe von Artikeln zum Starten:
|
||||
[http://clojure-doc.org/](http://clojure-doc.org/)
|
Loading…
Reference in New Issue
Block a user