Clojure - Kurzanleitung
Clojure ist eine dynamische funktionale Programmiersprache auf hohem Niveau. Clojure basiert auf der Programmiersprache LISP und verfügt über Compiler, mit denen es sowohl in der Java- als auch in der .NET-Laufzeitumgebung ausgeführt werden kann.
Bevor wir über Clojure sprechen, wollen wir nur eine kurze Beschreibung der LISP-Programmiersprache geben. LISPs haben einen winzigen Sprachkern, fast keine Syntax und eine leistungsstarke Makrofunktion. Mit diesen Funktionen können Sie LISP biegen, um es Ihrem Design anzupassen, anstatt umgekehrt. LISP ist seit 1958 dort.
Common LISP liest einen Ausdruck ein, wertet ihn aus und druckt dann das Ergebnis aus. Wenn Sie beispielsweise den Wert eines einfachen mathematischen Ausdrucks von 4 + 6 berechnen möchten, geben Sie ein.
USER(1) (+ 4 6)
Clojure verfolgt die folgenden Hauptziele als Programmiersprache.
Es basiert auf der Programmiersprache LISP, die die Code-Anweisungen kleiner macht als herkömmliche Programmiersprachen.
Es ist eine funktionale Programmiersprache.
Es konzentriert sich auf die Unveränderlichkeit. Dies ist im Grunde das Konzept, dass Sie keine Änderungen an Objekten vornehmen sollten, die an Ort und Stelle erstellt wurden.
Es kann den Status einer Anwendung für den Programmierer verwalten.
Es unterstützt Parallelität.
Es umfasst vorhandene Programmiersprachen. Beispielsweise kann Clojure das gesamte Java-Ökosystem für die Verwaltung der Ausführung des Codes über die JVM verwenden.
Die offizielle Website für Clojure ist https://clojure.org/
Es gibt verschiedene Möglichkeiten, mit Clojure als Programmiersprache zu arbeiten. Wir werden uns zwei Möglichkeiten ansehen, um mit der Clojure-Programmierung zu arbeiten.
Leiningen - Leiningen ist ein wesentliches Werkzeug zum Erstellen, Erstellen und Automatisieren von Clojure-Projekten.
Eclipse Plugin - Es gibt ein Plugin namens CounterClockwise, das für Eclipse verfügbar ist, um die Clojure-Entwicklung in der Eclipse-IDE durchzuführen.
Leiningen Installation
Stellen Sie sicher, dass die folgenden Systemanforderungen erfüllt sind, bevor Sie mit der Installation fortfahren.
System Anforderungen
JDK | JDK 1.7 oder höher |
---|---|
Erinnerung | 2 GB RAM (empfohlen) |
Step 1- Laden Sie die Binärinstallation herunter. Gehen Sie zum Linkhttp://leiningen-wininstallerum den Windows Installer zu bekommen. Klicken Sie auf die Option, um den Download des Groovy-Installationsprogramms zu starten.
Step 2 - Starten Sie das Installationsprogramm und klicken Sie auf die Schaltfläche Weiter.
Step 3 - Geben Sie den Speicherort für die Installation an und klicken Sie auf die Schaltfläche Weiter.
Step 4- Das Setup erkennt den Speicherort einer vorhandenen Java-Installation. Klicken Sie auf die Schaltfläche Weiter, um fortzufahren.
Step 5 - Klicken Sie auf die Schaltfläche Installieren, um die Installation zu starten.
Nach Abschluss der Installation haben Sie die Möglichkeit, eine Clojure-REPL zu öffnen. Hierbei handelt es sich um eine Umgebung, in der Sie Ihre Clojure-Programme erstellen und testen können.
Eclipse-Installation
Stellen Sie sicher, dass die folgenden Systemanforderungen erfüllt sind, bevor Sie mit der Installation fortfahren.
System Anforderungen
JDK | JDK 1.7 oder höher |
---|---|
Finsternis | Eclipse 4.5 (Mars) |
Step 1- Öffnen Sie Eclipse und klicken Sie auf den Menüpunkt. Klicken Sie auf Hilfe → Eclipse Marketplace.
Step 2- Geben Sie im angezeigten Dialogfeld das Schlüsselwort Clojure ein und klicken Sie auf die Schaltfläche "Los". Die Option gegen den Uhrzeigersinn wird angezeigt. Klicken Sie auf die Schaltfläche Installieren, um die Installation dieses Plugins zu starten.
Step 3 - Klicken Sie im nächsten Dialogfeld auf die Schaltfläche Bestätigen, um die Installation zu starten.
Step 4- Im nächsten Dialogfeld werden Sie aufgefordert, die Lizenzvereinbarung zu akzeptieren. Akzeptieren Sie die Lizenzvereinbarung und klicken Sie auf die Schaltfläche Fertig stellen, um mit der Installation fortzufahren.
Die Installation beginnt und fordert Sie nach Abschluss auf, Eclipse neu zu starten.
Nach dem Neustart von Eclipse wird in Eclipse die Option zum Erstellen eines neuen Clojure-Projekts angezeigt.
Um die grundlegende Syntax von Clojure zu verstehen, schauen wir uns zunächst ein einfaches Hello World-Programm an.
Hallo Welt als komplettes Programm
Schreiben Sie 'Hallo Welt' in ein vollständiges Clojure-Programm. Es folgt ein Beispiel.
Beispiel
(ns clojure.examples.hello
(:gen-class))
(defn hello-world []
(println "Hello World"))
(hello-world)
Die folgenden Dinge müssen über das obige Programm beachtet werden.
Das Programm wird in eine Datei namens main.clj geschrieben. Die Erweiterung 'clj' ist der Erweiterungsname für eine Clojure-Codedatei. Im obigen Beispiel heißt der Name der Datei main.clj.
Das Schlüsselwort 'defn' wird verwendet, um eine Funktion zu definieren. Wir werden Funktionen in Details in einem anderen Kapitel sehen. Aber jetzt wissen Sie, dass wir eine Funktion namens helloworld erstellen, die unseren Haupt-Clojure-Code enthält.
In unserem Clojure-Code verwenden wir die Anweisung 'println', um "Hello World" in die Konsolenausgabe zu drucken.
Wir rufen dann die Hallo-Welt-Funktion auf, die wiederum die Anweisung 'println' ausführt.
Das obige Programm erzeugt die folgende Ausgabe.
Ausgabe
Hello World
Allgemeine Form einer Erklärung
Die allgemeine Form einer Anweisung muss in Klammern angegeben werden, wie im folgenden Beispiel gezeigt.
(+ 1 2)
Im obigen Beispiel ist der gesamte Ausdruck in geschweiften Klammern eingeschlossen. Die Ausgabe der obigen Anweisung ist 3. Der Operator + verhält sich wie eine Funktion in Clojure, die zum Hinzufügen von Ziffern verwendet wird. Die Werte von 1 und 2 sind bekannt als parameters to the function.
Betrachten wir ein anderes Beispiel. In diesem Beispiel ist 'str' der Operator, mit dem zwei Zeichenfolgen verkettet werden. Die Zeichenfolgen "Hallo" und "Welt" werden als Parameter verwendet.
(str "Hello" "World")
Beispiel
Wenn wir die beiden obigen Anweisungen kombinieren und ein Programm schreiben, sieht es wie folgt aus.
(ns clojure.examples.hello
(:gen-class))
(defn Example []
(println (str "Hello World"))
(println (+ 1 2)))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
Hello World
3
Namespaces
Ein Namespace wird verwendet, um eine logische Grenze zwischen in Clojure definierten Modulen zu definieren.
Aktueller Namespace
Dies definiert den aktuellen Namespace, in dem sich der aktuelle Clojure-Code befindet.
Syntax
*ns*
Beispiel
Führen Sie im REPL-Befehlsfenster den folgenden Befehl aus.
*ns*
Ausgabe
Wenn wir den obigen Befehl ausführen, wird die Ausgabe abhängig vom aktuellen Namespace verschoben. Das Folgende ist ein Beispiel für eine Ausgabe. Der Namespace des Clojure-Codes lautet -
clojure.examples.hello
(ns clojure.examples.hello
(:gen-class))
(defn Example []
(println (str "Hello World"))
(println (+ 1 2)))
(Example)
Erklärung in Clojure erforderlich
Clojure-Code ist in Bibliotheken verpackt. Jede Clojure-Bibliothek gehört zu einem Namespace, der einem Java-Paket entspricht. Sie können eine Clojure-Bibliothek mit der Anweisung 'Require' laden.
Syntax
(require quoted-namespace-symbol)
Beispiel
Das Folgende ist ein Beispiel für die Verwendung dieser Anweisung.
(ns clojure.examples.hello
(:gen-class))
(require ‘clojure.java.io’)
(defn Example []
(.exists (file "Example.txt")))
(Example)
Im obigen Code verwenden wir das Schlüsselwort 'require', um den Namespace clojure.java.io zu importieren, der alle für die Eingabe- / Ausgabefunktionalität erforderlichen Funktionen enthält. Da wir nicht über die erforderliche Bibliothek verfügen, können wir die Funktion 'Datei' im obigen Code verwenden.
Kommentare in Clojure
Kommentare werden verwendet, um Ihren Code zu dokumentieren. Einzeilige Kommentare werden mit dem ;; an jeder Position in der Linie. Es folgt ein Beispiel.
Beispiel
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println "Hello World"))
(Example)
Trennzeichen
In Clojure können Anweisungen mithilfe der gekrümmten oder eckigen Klammern geteilt oder abgegrenzt werden.
Beispiel
Es folgen zwei Beispiele.
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println (+ 1 2 3)))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
6
Beispiel
Es folgt ein weiteres Beispiel.
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println [+ 1 2 3]))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
[#object[clojure.core$_PLUS_ 0x10f163b "clojure.core$_PLUS_@10f163b"] 1 2 3]
Leerzeichen
In Clojure können Leerzeichen verwendet werden, um verschiedene Komponenten einer Anweisung zur besseren Übersichtlichkeit aufzuteilen. Dies kann mit Hilfe des Kommas (,) erfolgen.
Zum Beispiel sind die folgenden zwei Anweisungen äquivalent und die Ausgabe beider Anweisungen ist 15.
(+ 1 2 3 4 5)
(+ 1, 2, 3, 4, 5)
Obwohl Clojure Kommas ignoriert, werden sie manchmal verwendet, um dem Programmierer das Lesen zu erleichtern.
Wenn Sie beispielsweise eine Hash-Map wie die folgende haben (def a-map {: a 1: b 2: c 3}) und im REPL-Fenster nach ihrem Wert fragen, druckt Clojure die Ausgabe als {: a 1, : b 2 ,: c 3}.
Die Ergebnisse sind leichter zu lesen, insbesondere wenn Sie eine große Datenmenge betrachten.
Symbole
In Clojure entsprechen Symbole Bezeichnern in anderen Programmiersprachen. Im Gegensatz zu anderen Programmiersprachen sieht der Compiler Symbole als tatsächliche Zeichenfolgenwerte. Da ein Symbol ein Wert ist, kann ein Symbol wie jedes andere Objekt in einer Sammlung gespeichert, als Argument an eine Funktion usw. übergeben werden.
Ein Symbol darf nur alphanumerische Zeichen und '* +! /. : - _? ' darf aber nicht mit einer Ziffer oder einem Doppelpunkt beginnen.
Es folgen gültige Beispiele für Symbole.
tutorial-point!
TUTORIAL
+tutorial+
Clojure Projektstruktur
Lassen Sie uns abschließend über eine typische Projektstruktur für ein Clojure-Projekt sprechen. Da Clojure-Code auf einer virtuellen Java-Maschine ausgeführt wird, ähnelt der größte Teil der Projektstruktur in Clojure dem, was Sie in einem Java-Projekt finden würden. Es folgt die Momentaufnahme einer Beispielprojektstruktur in Eclipse für ein Clojure-Projekt.
Die folgenden wichtigen Dinge müssen über die obige Programmstruktur beachtet werden.
demo_1 - Dies ist das Paket, in dem die Clojure-Codedatei abgelegt wird.
core.clj - Dies ist die Haupt-Clojure-Codedatei, die den Code für die Clojure-Anwendung enthält.
Der Ordner Leiningen enthält Dateien wie clojure-1.6.0.jar, die zum Ausführen einer Clojure-basierten Anwendung erforderlich sind.
Die Datei pom.properties enthält Informationen wie die Gruppen-ID, die Artefakt-ID und die Version des Clojure-Projekts.
Die Datei project.clj enthält Informationen zur Clojure-Anwendung. Im Folgenden finden Sie ein Beispiel für den Inhalt der Projektdatei.
(defproject demo-1 "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {
:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"
}
:dependencies [[org.clojure/clojure "1.6.0"]])
REPL (Read-Eval-Print-Schleife) ist ein Tool zum Experimentieren mit Clojure-Code. Sie können mit einem laufenden Programm interagieren und schnell ausprobieren, ob die Dinge so funktionieren, wie sie sollten. Dazu erhalten Sie eine Eingabeaufforderung, in die Sie den Code eingeben können. Anschließend wird Ihre Eingabe gelesen, ausgewertet, das Ergebnis gedruckt und eine Schleife erstellt, in der Sie erneut aufgefordert werden.
Dieser Prozess ermöglicht einen schnellen Feedback-Zyklus, der in den meisten anderen Sprachen nicht möglich ist.
Starten einer REPL-Sitzung
Eine REPL-Sitzung kann in Leiningen durch Eingabe des folgenden Befehls in die Befehlszeile gestartet werden.
lein repl
Dies öffnet das folgende REPL-Fenster.
Anschließend beginnen Sie bei Bedarf mit der Auswertung der Clojure-Befehle im REPL-Fenster.
Um eine REPL-Sitzung in Eclipse zu starten, klicken Sie auf die Menüoption und gehen Sie zu Ausführen als → Clojure-Anwendung.
Dadurch wird eine neue REPL-Sitzung in einem separaten Fenster zusammen mit der Konsolenausgabe gestartet.
Konzeptionell ähnelt REPL Secure Shell (SSH). Auf die gleiche Weise, wie Sie SSH für die Interaktion mit einem Remote-Server verwenden können, können Sie mit Clojure REPL mit einem laufenden Clojure-Prozess interagieren. Diese Funktion kann sehr leistungsfähig sein, da Sie sogar eine REPL an eine Live-Produktions-App anhängen und Ihr Programm während der Ausführung ändern können.
Spezielle Variablen in REPL
REPL enthält einige nützliche Variablen. Die häufig verwendete Variable ist die Spezialvariable * 1, * 2 und * 3. Diese werden verwendet, um die Ergebnisse der drei neuesten Ausdrücke auszuwerten.
Das folgende Beispiel zeigt, wie diese Variablen verwendet werden können.
user => "Hello"
Hello
user => "World"
World
user => (str *2 *1)
HelloWorld
Im obigen Beispiel werden die ersten beiden Zeichenfolgen als "Hallo" bzw. "Welt" an das REPL-Ausgabefenster gesendet. Dann werden die Variablen * 2 und * 1 verwendet, um die letzten 2 ausgewerteten Ausdrücke abzurufen.
Clojure bietet eine Vielzahl von built-in data types.
Integrierte Datentypen
Im Folgenden finden Sie eine Liste der Datentypen, die in Clojure definiert sind.
Integers - Nachfolgend finden Sie die Darstellung der in Clojure verfügbaren Ganzzahlen.
Decimal Integers (Short, Long and Int)- Diese werden verwendet, um ganze Zahlen darzustellen. Zum Beispiel 1234.
Octal Numbers- Diese werden verwendet, um Zahlen in oktaler Darstellung darzustellen. Zum Beispiel 012.
Hexadecimal Numbers- Diese werden verwendet, um Zahlen in der Darstellung darzustellen. Zum Beispiel 0xff.
Radix Numbers- Diese werden verwendet, um Zahlen in Radix-Darstellung darzustellen. Zum Beispiel 2r1111, wobei der Radix eine ganze Zahl zwischen 2 und einschließlich 36 ist.
Floating point
Die Standardeinstellung wird verwendet, um 32-Bit-Gleitkommazahlen darzustellen. Zum Beispiel 12.34.
Die andere Darstellung ist die wissenschaftliche Notation. Zum Beispiel 1.35e-12.
char- Dies definiert ein einzelnes Zeichenliteral. Zeichen werden mit dem Spielsymbol definiert. Zum Beispiel / e.
Boolean - Dies stellt einen booleschen Wert dar, der entweder wahr oder falsch sein kann.
String- Dies sind Textliterale, die in Form einer Zeichenkette dargestellt werden. Zum Beispiel "Hallo Welt".
Nil - Dies wird verwendet, um einen NULL-Wert in Clojure darzustellen.
Atom- Atome bieten eine Möglichkeit, den gemeinsamen, synchronen und unabhängigen Status zu verwalten. Sie sind ein Referenztyp wie refs und vars.
Gebundene Werte
Da alle Datentypen in Clojure von Java geerbt werden, sind die begrenzten Werte dieselben wie in der Programmiersprache Java. Die folgende Tabelle zeigt die maximal zulässigen Werte für die numerischen und dezimalen Literale.
Literale | Bereiche |
---|---|
Kurz | -32.768 bis 32.767 |
int | -2.147.483.648 bis 2.147.483.647 |
lange | -9.223.372.036.854.775.808 bis +9.223.372.036.854.775.807 |
schweben | 1.40129846432481707e-45 bis 3.40282346638528860e + 38 |
doppelt | 4.94065645841246544e-324d bis 1.79769313486231570e + 308d |
Klassennumerische Typen
Zusätzlich zu den primitiven Typen sind die folgenden Objekttypen (manchmal als Wrapper-Typen bezeichnet) zulässig.
Name |
---|
java.lang.Byte |
java.lang.Short |
java.lang.Integer |
java.lang.Long |
java.lang.Float |
java.lang.Double |
Beispiel
Das folgende Programm zeigt einen konsolidierten Clojure-Code, um die Datentypen in Clojure zu demonstrieren.
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
;; The below code declares a integer variable
(def x 1)
;; The below code declares a float variable
(def y 1.25)
;; The below code declares a string variable
(def str1 "Hello")
(println x)
(println y)
(println str1))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
1
1.25
Hello
In Clojure, variables sind definiert durch die ‘def’Stichwort. Es ist ein bisschen anders, wobei das Konzept der Variablen mehr mit dem Binden zu tun hat. In Clojure ist ein Wert an eine Variable gebunden. In Clojure ist zu beachten, dass Variablen unveränderlich sind. Damit sich der Wert der Variablen ändert, muss sie zerstört und neu erstellt werden.
Im Folgenden sind die grundlegenden Variablentypen in Clojure aufgeführt.
short- Dies wird verwendet, um eine kurze Zahl darzustellen. Zum Beispiel 10.
int- Dies wird verwendet, um ganze Zahlen darzustellen. Zum Beispiel 1234.
long- Dies wird verwendet, um eine lange Zahl darzustellen. Zum Beispiel 10000090.
float- Dies wird verwendet, um 32-Bit-Gleitkommazahlen darzustellen. Zum Beispiel 12.34.
char- Dies definiert ein einzelnes Zeichenliteral. Zum Beispiel '/ a'.
Boolean - Dies stellt einen booleschen Wert dar, der entweder wahr oder falsch sein kann.
String- Dies sind Textliterale, die in Form einer Zeichenkette dargestellt werden. Zum Beispiel "Hallo Welt".
Variable Deklarationen
Es folgt die allgemeine Syntax zum Definieren einer Variablen.
Syntax
(def var-name var-value)
Wobei 'var-name' der Name der Variablen und 'var-value' der an die Variable gebundene Wert ist.
Beispiel
Das Folgende ist ein Beispiel für eine Variablendeklaration.
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
;; The below code declares a integer variable
(def x 1)
;; The below code declares a float variable
(def y 1.25)
;; The below code declares a string variable
(def str1 "Hello")
;; The below code declares a boolean variable
(def status true))
(Example)
Variablen benennen
Der Name einer Variablen kann aus Buchstaben, Ziffern und dem Unterstrich bestehen. Es muss entweder mit einem Buchstaben oder einem Unterstrich beginnen. Groß- und Kleinbuchstaben unterscheiden sich, da Clojure genau wie Java eine Programmiersprache ist, bei der zwischen Groß- und Kleinschreibung unterschieden wird.
Beispiel
Im Folgenden finden Sie einige Beispiele für die Benennung von Variablen in Clojure.
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
;; The below code declares a Boolean variable with the name of status
(def status true)
;; The below code declares a Boolean variable with the name of STATUS
(def STATUS false)
;; The below code declares a variable with an underscore character.
(def _num1 2))
(Example)
Note - In den obigen Aussagen sind Status und STATUS aufgrund der Groß- / Kleinschreibung zwei verschiedene Variablendefinitionen in Clojure.
Das obige Beispiel zeigt, wie eine Variable mit einem Unterstrich definiert wird.
Variablen drucken
Da Clojure die JVM-Umgebung verwendet, können Sie auch die Funktion 'println' verwenden. Das folgende Beispiel zeigt, wie dies erreicht werden kann.
Beispiel
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
;; The below code declares a integer variable
(def x 1)
;; The below code declares a float variable
(def y 1.25)
;; The below code declares a string variable
(def str1 "Hello")
(println x)
(println y)
(println str1))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
1
1.25
Hello
Ein operator ist ein Symbol, das den Compiler anweist, bestimmte mathematische oder logische Manipulationen durchzuführen.
Clojure hat die folgenden Arten von Operatoren:
- Rechenzeichen
- Vergleichsoperatoren
- Logische Operatoren
- Bitweise Operatoren
Note - In Clojure arbeiten Operatoren und Operanden in der folgenden Syntax.
Syntax
(operator operand1 operand2 operandn)
Zum Beispiel,
Beispiel
(+ 1 2)
Das obige Beispiel führt eine arithmetische Operation für die Zahlen 1 und 2 durch.
Rechenzeichen
Die Clojure-Sprache unterstützt die normalen arithmetischen Operatoren wie jede andere Sprache. Im Folgenden sind die in Clojure verfügbaren arithmetischen Operatoren aufgeführt.
Beispiele anzeigen
Operator | Beschreibung | Beispiel |
---|---|---|
+ | Addition von zwei Operanden | (+ 1 2) ergibt 3 |
- - | Subtrahiert den zweiten Operanden vom ersten | (- 2 1) ergibt 1 |
* * | Multiplikation beider Operanden | (* 2 2) ergibt 4 |
/. | Division des Zählers durch Nenner | (float (/ 3 2)) ergibt 1,5 |
inc | Inkrementelle Operatoren, mit denen der Wert eines Operanden um 1 erhöht wird | inc 5 wird 6 geben |
dez | Inkrementelle Operatoren, mit denen der Wert eines Operanden um 1 verringert wird | 5. Dezember wird 4 geben |
max | Gibt das größte seiner Argumente zurück | max 1 2 3 gibt 3 zurück |
Mindest | Gibt das kleinste seiner Argumente zurück | min 1 2 3 gibt 1 zurück |
rem | Rest der Division der ersten Zahl durch die zweite | rem 3 2 ergibt 1 |
Vergleichsoperatoren
Vergleichsoperatoren ermöglichen den Vergleich von Objekten. Im Folgenden sind die in Clojure verfügbaren Vergleichsoperatoren aufgeführt.
Beispiele anzeigen
Operator | Beschreibung | Beispiel |
---|---|---|
= | Testet die Gleichheit zwischen zwei Objekten | (= 2 2) ergibt true |
nicht = | Testet den Unterschied zwischen zwei Objekten | (nicht = 3 2) wird wahr geben |
< | Überprüft, ob das linke Objekt kleiner als der rechte Operand ist | (<2 3) wird wahr geben |
<= | Überprüft, ob das linke Objekt kleiner oder gleich dem rechten Operanden ist | (<= 2 3) ergibt true |
> | Überprüft, ob das linke Objekt größer als der rechte Operand ist | (> 3 2) wird wahr geben |
> = | Überprüft, ob das linke Objekt größer oder gleich dem rechten Operanden ist | (> = 3 2) ergibt true |
Logische Operatoren
Logische Operatoren werden verwendet, um boolesche Ausdrücke auszuwerten. Im Folgenden sind die in Groovy verfügbaren logischen Operatoren aufgeführt.
Beispiele anzeigen
Operator | Beschreibung | Beispiel |
---|---|---|
and | Dies ist der logische Operator "und" | (oder wahr wahr) wird wahr geben |
or | Dies ist der logische "oder" -Operator | (und wahr falsch) wird falsch geben |
not | Dies ist der logische "Nicht" -Operator | (nicht falsch) wird wahr geben |
Das folgende Codefragment zeigt, wie die verschiedenen Operatoren verwendet werden können.
Bitweise Operatoren
Clojure bietet vier bitweise Operatoren. Im Folgenden sind die in Clojure verfügbaren bitweisen Operatoren aufgeführt.
Beispiele anzeigen
Sr.Nr. | Betreiber & Beschreibung |
---|---|
1 | bit-and Dies ist der bitweise "und" -Operator |
2 | bit-or Dies ist der bitweise "oder" -Operator |
3 | bit-xor Dies ist der bitweise Operator "xor" oder Exclusive "oder" |
4 | bit-not Dies ist der bitweise Negationsoperator |
Im Folgenden finden Sie die Wahrheitstabelle, in der diese Operatoren aufgeführt sind.
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
Vorrang des Bedieners
Wie bei LISPs im Allgemeinen besteht kein Grund zur Sorge um die Priorität des Bedieners. Dies ist einer der Vorteile von S-Expressions und Präfixnotation. Alle Funktionen werden von links nach rechts und von innen nach außen ausgewertet. Die Operatoren in Clojure sind nur Funktionen, und alles ist vollständig in Klammern gesetzt.
Bisher haben wir Anweisungen gesehen, die nacheinander sequentiell ausgeführt werden. Zusätzlich werden in Clojure Anweisungen bereitgestellt, um den Kontrollfluss in der Logik eines Programms zu ändern. Sie werden dann in Kontrollflussanweisungen eingeteilt, die wir im Detail sehen werden.
Sr.Nr. | Schleifen & Beschreibung |
---|---|
1 | While-Anweisung Das 'while' Die Anweisung wird ausgeführt, indem zuerst der Bedingungsausdruck (ein Boolescher Wert) ausgewertet wird. Wenn das Ergebnis wahr ist, werden die Anweisungen in der while-Schleife ausgeführt. |
2 | Doseq-Anweisung Das ‘doseq’Die Anweisung ähnelt der Anweisung 'für jede', die in vielen anderen Programmiersprachen enthalten ist. Die Dosis-Q-Anweisung wird grundsätzlich verwendet, um eine Sequenz zu durchlaufen. |
3 | Dotimes Statement Das ‘dotimes’ Anweisung wird verwendet, um eine Anweisung 'x' mehrmals auszuführen. |
4 | Schleifenanweisung Die Schleifen-Sonderform ist nicht wie eine ‘for’Schleife. Die Verwendung der Schleife entspricht der let-Bindung. Die Schleife setzt jedoch einen Rekursionspunkt |
Decision-making structures erfordern, dass der Programmierer eine oder mehrere Bedingungen angibt, die vom Programm ausgewertet oder getestet werden sollen, zusammen mit einer Anweisung oder Anweisungen, die ausgeführt werden sollen, wenn die Bedingung als wahr bestimmt wird, und optional andere Anweisungen, die ausgeführt werden sollen, wenn die Bedingung bestimmt wird sei falsch.
Sr.Nr. | Methoden & Beschreibung |
---|---|
1 | If-Anweisung In Clojure ist die Bedingung ein Ausdruck, der sie entweder als wahr oder falsch bewertet. 'If' Wenn die Bedingung erfüllt ist, wird Anweisung Nr. 1 ausgeführt, andernfalls wird Anweisung Nr. 2 ausgeführt. |
2 | If / do-Ausdruck Das ‘if-do’ Ausdruck in Clojure wird verwendet, um die Ausführung mehrerer Ausdrücke für jeden Zweig der 'if'-Anweisung zu ermöglichen. |
3 | Verschachtelte If-Anweisung Mehrere 'if' ineinander eingebettete Anweisungen. |
4 | Fallbeschreibung Clojure bietet die ‘case’ Aussage, die der ähnlich ist ‘switch’ Anweisung in der Programmiersprache Java verfügbar. |
5 | Cond Statement Clojure bietet eine weitere Bewertungserklärung mit dem Namen ‘cond’Erklärung. Diese Anweisung benötigt eine Reihe von Test / Ausdruckspaaren. |
Clojure ist als funktionale Programmiersprache bekannt, daher ist zu erwarten, dass die Funktionsweise von Funktionen in Clojure stark betont wird. In diesem Kapitel wird beschrieben, was mit Funktionen in Clojure alles möglich ist.
Sr.Nr. | Funktionen & Beschreibung |
---|---|
1 | Funktion definieren Eine Funktion wird mit dem definiert ‘defn’ Makro. |
2 | Anonyme Funktionen Eine anonyme Funktion ist eine Funktion, der kein Name zugeordnet ist. |
3 | Funktionen mit mehreren Argumenten Clojure-Funktionen können mit null oder mehr Parametern definiert werden. Die Werte, die Sie an Funktionen übergeben, werden aufgerufenarguments, und die Argumente können von einem beliebigen Typ sein. |
4 | Variadische Funktionen Clojure bietet die 'case'-Anweisung an, die der in der Java-Programmiersprache verfügbaren' switch'-Anweisung ähnelt. |
5 | Funktionen höherer Ordnung Funktionen höherer Ordnung (HOFs) sind Funktionen, die andere Funktionen als Argumente verwenden. HOFs sind eine wichtige funktionale Programmiertechnik und werden in Clojure häufig verwendet. |
Numbers Der Datentyp in Clojure wird von Java-Klassen abgeleitet.
Clojure unterstützt Ganzzahl- und Gleitkommazahlen.
Eine Ganzzahl ist ein Wert, der keinen Bruch enthält.
Eine Gleitkommazahl ist ein Dezimalwert, der einen Dezimalbruch enthält.
Es folgt ein Beispiel für Zahlen in Clojure.
(def x 5)
(def y 5.25)
Wobei 'x' vom Typ ist Integer und 'y' ist das float.
In Java werden die folgenden Klassen an die in Clojure definierten Nummern angehängt.
Um tatsächlich zu sehen, dass die Zahlen in Clojure von Java-Klassen abgeleitet sind, verwenden Sie das folgende Programm, um den Typ der zugewiesenen Zahlen zu sehen, wenn Sie den Befehl 'def' verwenden.
Beispiel
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(def x 5)
(def y 5.25)
(println (type x))
(println (type y)))
(Example)
Das ‘type’ Mit dem Befehl wird die Klasse ausgegeben, die dem einer Variablen zugewiesenen Wert zugeordnet ist.
Ausgabe
Der obige Code erzeugt die folgende Ausgabe.
Java.lang.long
Java.lang.double
Zahlentests
Die folgenden Testfunktionen stehen für Zahlen zur Verfügung.
Sr.Nr. | Zahlen & Beschreibung |
---|---|
1 | Null? Gibt true zurück, wenn die Zahl Null ist, andernfalls false. |
2 | pos? Gibt true zurück, wenn die Zahl größer als Null ist, andernfalls false. |
3 | neg? Gibt true zurück, wenn die Zahl kleiner als Null ist, andernfalls false. |
4 | sogar? Gibt true zurück, wenn die Zahl gerade ist, und löst eine Ausnahme aus, wenn die Zahl keine Ganzzahl ist. |
5 | seltsam? Gibt true zurück, wenn die Zahl ungerade ist, und löst eine Ausnahme aus, wenn die Zahl keine Ganzzahl ist. |
6 | Nummer? Gibt true zurück, wenn die Zahl wirklich eine Zahl ist. |
7 | ganze Zahl? Gibt true zurück, wenn die Zahl eine Ganzzahl ist. |
8 | schweben? Gibt true zurück, wenn die Zahl ein Float ist. |
Wir haben die recur-Anweisung in einem früheren Thema gesehen, und während die 'for'-Schleife einer Schleife ähnelt, recur ist eine echte Schleife in Clojure.
Wenn Sie einen Programmierhintergrund haben, haben Sie möglicherweise von einer Schwanzrekursion gehört, die ein Hauptmerkmal funktionaler Sprachen ist. Diese wiederkehrende Sonderform implementiert die Schwanzrekursion. Wie das Wort "Schwanzrekursion" anzeigt, muss die Wiederholung in der Schwanzposition aufgerufen werden. Mit anderen Worten, Wiederholung muss das letzte sein, was bewertet werden muss.
Das einfachste Beispiel für die recur-Anweisung wird in der 'for'-Schleife verwendet. Im folgenden Beispiel wird die Anweisung recur verwendet, um den Wert der Variablen 'i' zu ändern und den Wert der Variablen an den Schleifenausdruck zurückzugeben.
Beispiel
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(loop [i 0]
(when (< i 5)
(println i)
(recur (inc i)))))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
0
1
2
3
4
Clojure bietet eine Reihe von Hilfsmethoden für die Arbeit mit E / A. Es bietet einfachere Klassen, um die folgenden Funktionen für Dateien bereitzustellen.
- Dateien lesen
- Schreiben in Dateien
- Überprüfen, ob eine Datei eine Datei oder ein Verzeichnis ist
Lassen Sie uns einige der Dateivorgänge untersuchen, die Clojure zu bieten hat.
Lesen des Inhalts einer Datei als ganze Zeichenfolge
Wenn Sie den gesamten Inhalt der Datei als Zeichenfolge abrufen möchten, können Sie die verwenden clojure.core.slurpMethode. Der Befehl slurp öffnet einen Reader für eine Datei, liest den gesamten Inhalt und gibt eine Zeichenfolge zurück.
Das Folgende ist ein Beispiel dafür, wie dies getan werden kann.
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(def string1 (slurp "Example.txt"))
(println string1))
(Example)
Wenn die Datei die folgenden Zeilen enthält, werden sie wie folgt gedruckt:
line : Example1
line : Example2
Lesen des Inhalts einer Datei zeilenweise
Wenn Sie den gesamten Inhalt der Datei zeilenweise als Zeichenfolge abrufen möchten, können Sie die verwenden clojure.java.io/readerMethode. Die Klasse clojure.java.io/reader erstellt einen Lesepuffer, mit dem jede Zeile der Datei gelesen wird.
Das folgende Beispiel zeigt, wie dies getan werden kann.
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(with-open [rdr (clojure.java.io/reader "Example.txt")]
(reduce conj [] (line-seq rdr))))
(Example)
Wenn die Datei die folgenden Zeilen enthält, werden sie wie folgt gedruckt:
line : Example1
line : Example2
Die Ausgabe wird angezeigt als -
["line : Example1" "line : Example2"]
Schreiben in Dateien
Wenn Sie in Dateien schreiben möchten, können Sie die verwenden clojure.core.spitBefehl zum Spucken ganzer Zeichenfolgen in Dateien. Der Befehl spit ist das Gegenteil der Slurp-Methode. Diese Methode öffnet eine Datei als Writer, schreibt Inhalte und schließt die Datei.
Es folgt ein Beispiel.
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(spit "Example.txt"
"This is a string"))
Wenn Sie im obigen Beispiel den Inhalt der Datei Example.txt sehen, sehen Sie den Inhalt von "Dies ist eine Zeichenfolge".
Schreiben von 'in' Dateien zeilenweise
Wenn Sie zeilenweise in Dateien schreiben möchten, können Sie die verwenden clojure.java.io.writerKlasse. Die Klasse clojure.java.io.writer wird verwendet, um einen Writer-Stream zu erstellen, bei dem Datenbytes in den Stream und anschließend in die Datei eingespeist werden.
Das folgende Beispiel zeigt, wie der Befehl spit verwendet werden kann.
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(with-open [w (clojure.java.io/writer "Example.txt" :append true)]
(.write w (str "hello" "world"))))
(Example)
Wenn der obige Code ausgeführt wird, ist die Zeile "Hallo Welt" in der Datei Example.txt vorhanden. Die Option append: true besteht darin, Daten an die Datei anzuhängen. Wenn diese Option nicht angegeben ist, wird die Datei überschrieben, wenn Daten in die Datei geschrieben werden.
Überprüfen, ob eine Datei vorhanden ist
Um zu überprüfen, ob eine Datei vorhanden ist, klicken Sie auf clojure.java.io.fileKlasse kann verwendet werden, um das Vorhandensein einer Datei zu überprüfen. Das folgende Beispiel zeigt, wie dies erreicht werden kann.
(ns clojure.examples.hello
(:gen-class))
;; This program displays Hello World
(defn Example []
(println (.exists (clojure.java.io/file "Example.txt"))))
(Example)
Wenn die Datei Example.txt vorhanden ist, ist die Ausgabe wahr.
Lesen von der Konsole
Um Daten von der Konsole zu lesen, müssen Sie die read-lineAnweisung kann verwendet werden. Das folgende Beispiel zeigt, wie dies verwendet werden kann.
Wenn Sie den Befehl (Zeile lesen) im REPL-Fenster eingeben, haben Sie die Möglichkeit, Eingaben in das Konsolenfenster einzugeben.
user->(read-line)
Hello World
Der obige Code erzeugt die folgende Ausgabe.
“Hello World”
EIN StringDas Literal wird in Clojure erstellt, indem der Zeichenfolgentext in Anführungszeichen gesetzt wird. Strings in Clojure müssen mit doppelten Anführungszeichen wie „Hello World“ erstellt werden.
Beispiel
Im Folgenden finden Sie ein Beispiel für die Verwendung von Zeichenfolgen in Clojure.
(ns clojure.examples.hello
(:gen-class))
(defn hello-world []
(println "Hello World")
(println "This is a demo application"))
(hello-world)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
Hello World
This is a demo application
Grundlegende Zeichenfolgenoperationen
Clojure verfügt über eine Reihe von Operationen, die für Zeichenfolgen ausgeführt werden können. Es folgen die Operationen.
Sr.Nr. | String-Operationen & Beschreibung |
---|---|
1 | str Die Verkettung von Strings kann durch die einfache str-Funktion erfolgen. |
2 | Format Die Formatierung von Zeichenfolgen kann über die einfache Formatierungsfunktion erfolgen. Die Formatierungsfunktion formatiert eine Zeichenfolge mitjava.lang.String.format. |
3 | Anzahl Gibt die Anzahl der Zeichen in der Zeichenfolge zurück. |
4 | subs Gibt die Teilzeichenfolge von 's' zurück, die am Anfang einschließlich beginnt und am Ende endet (standardmäßig die Länge der Zeichenfolge). |
5 | vergleichen Sie Gibt eine negative Zahl, Null oder eine positive Zahl zurück, wenn 'x' logischerweise 'kleiner als', 'gleich' oder 'größer als' 'y' ist. |
6 | Kleinbuchstaben Konvertiert Zeichenfolge in Kleinbuchstaben. |
7 | Großbuchstaben Konvertiert Zeichenfolge in Großbuchstaben. |
8 | beitreten Gibt eine Zeichenfolge aller Elemente in der Sammlung zurück, die von (seq collection) zurückgegeben wird und durch ein optionales Trennzeichen getrennt ist. |
9 | Teilt Teilt die Zeichenfolge auf einen regulären Ausdruck. |
10 | Trennlinien Geteilte Zeichenfolgen basieren auf den Escape-Zeichen \ n oder \ r \ n. |
11 | umkehren Kehrt die Zeichen in einer Zeichenfolge um. |
12 | ersetzen Ersetzt alle Instanzen einer Übereinstimmung in einer Zeichenfolge durch die Ersatzzeichenfolge. |
13 | trimmen Entfernt Leerzeichen von beiden Enden der Zeichenfolge. |
14 | triml Entfernt Leerzeichen von der linken Seite der Zeichenfolge. |
15 | trimr Entfernt Leerzeichen von der rechten Seite der Zeichenfolge. |
Listist eine Struktur zum Speichern einer Sammlung von Datenelementen. In Clojure implementiert die Liste dieISeqSchnittstelle. Listen werden in Clojure mithilfe der Listenfunktion erstellt.
Beispiel
Im Folgenden finden Sie ein Beispiel für die Erstellung einer Zahlenliste in Clojure.
(ns clojure.examples.example
(:gen-class))
(defn example []
(println (list 1 2 3 4)))
(example)
Ausgabe
Der obige Code erzeugt die folgende Ausgabe.
(1 2 3 4)
Im Folgenden finden Sie ein Beispiel für das Erstellen einer Liste von Zeichen in Clojure.
(ns clojure.examples.example
(:gen-class))
(defn example []
(println (list 'a 'b 'c 'd)))
(example)
Der obige Code erzeugt die folgende Ausgabe.
(a b c d)
Im Folgenden sind die in Clojure verfügbaren Listenmethoden aufgeführt.
Sr.Nr. | Listen & Beschreibung |
---|---|
1 | Liste* Erstellt eine neue Liste mit den vorangestellten Elementen, von denen das letzte als Sequenz behandelt wird. |
2 | zuerst Diese Funktion gibt das erste Element in der Liste zurück. |
3 | n Diese Funktion gibt das Element an der 'n-ten' Position in der Liste zurück. |
4 | Nachteile Gibt eine neue Liste zurück, in der ein Element am Anfang der Liste hinzugefügt wird. |
5 | konj Gibt eine neue Liste zurück, in der sich die Liste am Anfang befindet und die anzuhängenden Elemente am Ende platziert werden. |
6 | sich ausruhen Gibt die verbleibenden Elemente in der Liste nach dem ersten Element zurück. |
SetsIn Clojure gibt es eine Reihe eindeutiger Werte. Sets werden in Clojure mit Hilfe des Befehls set erstellt.
Beispiel
Im Folgenden finden Sie ein Beispiel für die Erstellung von Sets in Clojure.
(ns clojure.examples.example
(:gen-class))
(defn example []
(println (set '(1 1 2 2))))
(example)
Ausgabe
Der obige Code erzeugt die folgende Ausgabe.
#{1,2}
Im Folgenden sind die in Clojure verfügbaren Methoden für Sets aufgeführt.
Sr.Nr. | Sets & Beschreibung |
---|---|
1 | sortiert-gesetzt Gibt eine sortierte Menge von Elementen zurück. |
2 | bekommen Gibt das Element an der Indexposition zurück. |
3 | enthält? Findet heraus, ob die Menge ein bestimmtes Element enthält oder nicht. |
4 | konj Hängt ein Element an die Menge an und gibt die neue Menge von Elementen zurück. |
5 | disj Trennt ein Element von der Menge. |
6 | Union Gibt eine Menge zurück, die die Vereinigung der Eingabesätze darstellt |
7 | Unterschied Gibt eine Menge zurück, die die erste Menge ohne Elemente der verbleibenden Mengen ist. |
8 | Überschneidung Gibt eine Menge zurück, die der Schnittpunkt der Eingabesätze ist. |
9 | Teilmenge? Ist set1 eine Teilmenge von set2? |
10 | Obermenge? Ist set1 eine Obermenge von set2? |
EIN Vectorist eine Sammlung von Werten, die durch zusammenhängende Ganzzahlen indiziert sind. Ein Vektor wird mithilfe der Vektormethode in Clojure erstellt.
Beispiel
Im Folgenden finden Sie ein Beispiel für die Erstellung eines Vektors in Clojure.
(ns clojure.examples.example
(:require [clojure.set :as set])
(:gen-class))
(defn example []
(println (vector 1 2 3)))
(example)
Ausgabe
Der obige Code erzeugt die folgende Ausgabe.
[1 2 3]
Im Folgenden sind die in Clojure verfügbaren Methoden aufgeführt.
Sr.Nr. | Vektoren & Beschreibung |
---|---|
1 | Vektor-von Erstellt einen neuen Vektor eines einzelnen primitiven Typs 't', wobei 't' einer der folgenden Werte ist: int: long: float: double: byte: short: char oder: boolean. |
2 | n Diese Funktion gibt das Element an der n-ten Position im Vektor zurück. |
3 | bekommen Gibt das Element an der Indexposition im Vektor zurück. |
4 | konj Hängt ein Element an den Vektor an und gibt den neuen Satz von Vektorelementen zurück. |
5 | Pop Gibt für eine Liste oder Warteschlange eine neue Liste / Warteschlange ohne das erste Element zurück. Für einen Vektor wird ein neuer Vektor ohne das letzte Element zurückgegeben. |
6 | subvec Gibt einen Untervektor von einem Start- und Endindex zurück. |
EIN Mapist eine Sammlung, die Schlüssel Werten zuordnet. Es werden zwei verschiedene Kartentypen bereitgestellt - gehasht und sortiert.HashMaps benötigen Schlüssel, die hashCode korrekt unterstützen und gleich sind. SortedMaps erfordern Schlüssel, die Comparable implementieren, oder eine Instanz von Comparator.
Eine Karte kann auf zwei Arten erstellt werden, die erste erfolgt über die Hash-Map-Methode.
Erstellung - HashMaps
HashMaps haben eine typische Schlüsselwertbeziehung und werden mithilfe der Hash-Map-Funktion erstellt.
(ns clojure.examples.example
(:gen-class))
(defn example []
(def demokeys (hash-map "z" "1" "b" "2" "a" "3"))
(println demokeys))
(example)
Ausgabe
Der obige Code erzeugt die folgende Ausgabe.
{z 1, b 2, a 3}
Erstellung - SortedMaps
SortedMaps haben die einzigartige Eigenschaft, ihre Elemente nach dem Schlüsselelement zu sortieren. Das folgende Beispiel zeigt, wie die sortierte Karte mit der Funktion "Sortierte Karte" erstellt werden kann.
(ns clojure.examples.example
(:gen-class))
(defn example []
(def demokeys (sorted-map "z" "1" "b" "2" "a" "3"))
(println demokeys))
(example)
Der obige Code erzeugt die folgende Ausgabe.
{a 3, b 2, z 1}
Aus dem obigen Programm können Sie deutlich erkennen, dass die Elemente in den Karten nach dem Schlüsselwert sortiert sind. Im Folgenden sind die für Karten verfügbaren Methoden aufgeführt.
Sr.Nr. | Karten & Beschreibung |
---|---|
1 | bekommen Gibt den Wert zurück, der dem Schlüssel zugeordnet ist, nicht gefunden oder null, wenn der Schlüssel nicht vorhanden ist. |
2 | enthält? Überprüfen Sie, ob die Karte einen erforderlichen Schlüssel enthält. |
3 | finden Gibt den Karteneintrag für den Schlüssel zurück. |
4 | Schlüssel Gibt die Liste der Schlüssel in der Karte zurück. |
5 | vals Gibt die Liste der Werte in der Karte zurück. |
6 | dissoc Trennt einen Schlüsselwerteintrag von der Karte. |
7 | verschmelzen Fügt zwei Karteneinträge zu einem einzigen Karteneintrag zusammen. |
8 | verbinden mit Gibt eine Karte zurück, die aus den restlichen Karten besteht, die mit der ersten verbunden sind. |
9 | Auswahltasten Gibt eine Karte zurück, die nur die Einträge in der Karte enthält, deren Schlüssel in Schlüsseln liegt. |
10 | Schlüssel umbenennen Benennt die Schlüssel in der aktuellen HashMap in die neu definierten um. |
11 | Map-Invert Invertiert die Karten, sodass die Werte zu Schlüsseln werden und umgekehrt. |
Namespacesin Clojure werden verwendet, um Klassen in separate logische Räume zu differenzieren, genau wie in Java. Betrachten Sie die folgende Aussage.
(:require [clojure.set :as set])
In der obigen Anweisung ist 'clojure.set' ein Namespace, der verschiedene Klassen und Methoden enthält, die im Programm verwendet werden sollen. Der obige Namespace enthält beispielsweise die Funktion map-invert, mit der eine Karte mit Schlüsselwerten invertiert wird. Wir können diese Funktion nur verwenden, wenn wir unser Programm ausdrücklich anweisen, diesen Namespace einzuschließen.
Schauen wir uns die verschiedenen Methoden an, die für Namespaces verfügbar sind.
Sr.Nr. | Methoden & Beschreibung |
---|---|
1 | * ns * Dies wird verwendet, um Ihren aktuellen Namespace anzuzeigen. |
2 | ns Dies wird verwendet, um einen neuen Namespace zu erstellen und ihn dem laufenden Programm zuzuordnen. |
3 | alias Fügen Sie einem anderen Namespace einen Alias im aktuellen Namespace hinzu. Argumente sind zwei Symbole: der zu verwendende Alias und der symbolische Name des Ziel-Namespace. |
4 | all-ns Gibt eine Liste aller Namespaces zurück. |
5 | find-ns Findet einen bestimmten Namespace und gibt ihn zurück. |
6 | ns-name Gibt den Namen eines bestimmten Namespace zurück. |
7 | ns-Aliase Gibt die Aliase zurück, die beliebigen Namespaces zugeordnet sind. |
8 | ns-map Gibt eine Karte aller Zuordnungen für den Namespace zurück. |
9 | Un-Alias Gibt eine Karte zurück, die nur die Einträge in der Karte enthält, deren Schlüssel in Schlüsseln liegt. |
Exception handlingist in jeder Programmiersprache erforderlich, um die Laufzeitfehler zu behandeln, damit der normale Ablauf der Anwendung aufrechterhalten werden kann. Ausnahmen stören normalerweise den normalen Ablauf der Anwendung. Aus diesem Grund müssen wir in unserer Anwendung die Ausnahmebehandlung verwenden.
Die Ausnahme wird grob in die folgenden Kategorien eingeteilt:
Checked Exception- Die Klassen, die die Throwable-Klasse mit Ausnahme von RuntimeException und Error erweitern, werden als geprüfte Ausnahmen bezeichnet. ZB IOException, SQLException usw. Überprüfte Ausnahmen werden zur Kompilierungszeit überprüft.
Betrachten wir das folgende Programm, das eine Operation für eine Datei namens Example.txt ausführt. Es kann jedoch immer einen Fall geben, in dem die Datei Example.txt nicht vorhanden ist.
(ns clojure.examples.example
(:gen-class))
;; This program displays Hello World
(defn Example []
(def string1 (slurp "Example.txt"))
(println string1))
(Example)
Wenn die Datei Example.txt nicht vorhanden ist, wird vom Programm die folgende Ausnahme generiert.
Caused by: java.io.FileNotFoundException: Example.txt (No such file or
directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at clojure.java.io$fn__9185.invoke(io.clj:229) at clojure.java.io$fn__9098$G__9091__9105.invoke(io.clj:69) at clojure.java.io$fn__9197.invoke(io.clj:258)
at clojure.java.io$fn__9098$G__9091__9105.invoke(io.clj:69)
Aus der obigen Ausnahme können wir deutlich erkennen, dass das Programm eine FileNotFoundException ausgelöst hat.
Unchecked Exception- Die Klassen, die RuntimeException erweitern, werden als ungeprüfte Ausnahmen bezeichnet. Beispiel: ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException usw. Nicht aktivierte Ausnahmen werden nicht zur Kompilierungszeit, sondern zur Laufzeit überprüft.
Ein klassischer Fall ist die ArrayIndexOutOfBoundsException, die auftritt, wenn Sie versuchen, auf einen Index eines Arrays zuzugreifen, der größer als die Länge des Arrays ist. Das Folgende ist ein typisches Beispiel für diese Art von Fehler.
(ns clojure.examples.example
(:gen-class))
(defn Example []
(try
(aget (int-array [1 2 3]) 5)
(catch Exception e (println (str "caught exception: " (.toString e))))
(finally (println "This is our final block")))
(println "Let's move on"))
(Example)
Wenn der obige Code ausgeführt wird, wird die folgende Ausnahme ausgelöst.
caught exception: java.lang.ArrayIndexOutOfBoundsException: 5
This is our final block
Let's move on
Error
Fehler können nicht behoben werden, z. B. OutOfMemoryError, VirtualMachineError, AssertionError usw. Dies sind Fehler, die das Programm niemals beheben kann und die zum Absturz des Programms führen. Wir brauchen jetzt einen Mechanismus, um diese Ausnahmen abzufangen, damit das Programm weiter ausgeführt werden kann, wenn diese Ausnahmen existieren.
Das folgende Diagramm zeigt, wie die Hierarchie der Ausnahmen in Clojure organisiert ist. Es basiert alles auf der in Java definierten Hierarchie.
Ausnahmen fangen
Genau wie andere Programmiersprachen bietet Clojure den normalen 'try-catch'-Block, um Ausnahmen abzufangen, sobald sie auftreten.
Es folgt die allgemeine Syntax des Try-Catch-Blocks.
(try
(//Protected code)
catch Exception e1)
(//Catch block)
Ihr gesamter Code, der eine Ausnahme auslösen könnte, befindet sich in der Protected code block.
In dem catch blockkönnen Sie benutzerdefinierten Code schreiben, um Ihre Ausnahme zu behandeln, damit die Anwendung die Ausnahme wiederherstellen kann.
Schauen wir uns unser früheres Beispiel an, in dem eine Ausnahme für nicht gefundene Dateien generiert wurde, und sehen wir, wie wir den try catch-Block verwenden können, um die vom Programm ausgelöste Ausnahme abzufangen.
(ns clojure.examples.example
(:gen-class))
(defn Example []
(try
(def string1 (slurp "Example.txt"))
(println string1)
(catch Exception e (println (str "caught exception: " (.getMessage e))))))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
caught exception: Example.txt (No such file or directory)
Aus dem obigen Code schließen wir fehlerhaften Code in den try block. Im catch-Block fangen wir nur unsere Ausnahme ab und geben eine Nachricht aus, dass eine Ausnahme aufgetreten ist. Wir haben jetzt eine sinnvolle Möglichkeit, die vom Programm generierte Ausnahme zu erfassen.
Mehrere Fangblöcke
Man kann mehrere Catch-Blöcke haben, um mehrere Arten von Ausnahmen zu behandeln. Abhängig von der Art der ausgelösten Ausnahme würden Sie für jeden catch-Block Code schreiben, um ihn entsprechend zu behandeln.
Lassen Sie uns unseren früheren Code so ändern, dass er zwei Catch-Blöcke enthält, von denen einer für die Ausnahme "Datei nicht gefunden" spezifisch ist und der andere für einen allgemeinen Ausnahmeblock.
(ns clojure.examples.example
(:gen-class))
(defn Example []
(try
(def string1 (slurp "Example.txt"))
(println string1)
(catch java.io.FileNotFoundException e (println (str "caught file
exception: " (.getMessage e))))
(catch Exception e (println (str "caught exception: " (.getMessage e)))))
(println "Let's move on"))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
caught file exception: Example.txt (No such file or directory)
Let's move on
Aus der obigen Ausgabe können wir deutlich erkennen, dass unsere Ausnahme vom Catch-Block 'FileNotFoundException' und nicht vom allgemeinen Catch-Block abgefangen wurde.
Endlich blockieren
Der finally-Block folgt einem try-Block oder einem catch-Block. Ein endgültiger Codeblock wird immer ausgeführt, unabhängig vom Auftreten einer Ausnahme.
Mit einem finally-Block können Sie alle Anweisungen vom Bereinigungstyp ausführen, die Sie ausführen möchten, unabhängig davon, was im geschützten Code geschieht. Es folgt die Syntax für diesen Block.
(try
(//Protected code)
catch Exception e1)
(//Catch block)
(finally
//Cleanup code)
Lassen Sie uns den obigen Code ändern und den endgültigen Codeblock hinzufügen. Es folgt das Code-Snippet.
(ns clojure.examples.example
(:gen-class))
(defn Example []
(try
(def string1 (slurp "Example.txt"))
(println string1)
(catch java.io.FileNotFoundException e (println (str "caught file
exception: " (.getMessage e))))
(catch Exception e (println (str "caught exception: " (.getMessage e))))
(finally (println "This is our final block")))
(println "Let's move on"))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
caught file exception: Example.txt (No such file or directory)
This is our final block
Let's move on
Aus dem obigen Programm können Sie ersehen, dass der letzte Block auch implementiert wird, nachdem der catch-Block die erforderliche Ausnahme abgefangen hat.
Da Clojure seine Ausnahmebehandlung ähnlich wie Java von Java ableitet, stehen in Clojure die folgenden Methoden zum Verwalten der Ausnahmen zur Verfügung.
public String getMessage()- Gibt eine detaillierte Nachricht über die aufgetretene Ausnahme zurück. Diese Nachricht wird im Throwable-Konstruktor initialisiert.
public Throwable getCause() - Gibt die Ursache der Ausnahme zurück, die durch ein Throwable-Objekt dargestellt wird.
public String toString() - Gibt den Namen der Klasse zurück, die mit dem Ergebnis von getMessage () verknüpft ist.
public void printStackTrace() - Druckt das Ergebnis von toString () zusammen mit dem Stack-Trace an System.err, den Fehlerausgabestream.
public StackTraceElement [] getStackTrace()- Gibt ein Array zurück, das jedes Element in der Stapelverfolgung enthält. Das Element am Index 0 repräsentiert den oberen Rand des Aufrufstapels, und das letzte Element im Array repräsentiert die Methode am unteren Rand des Aufrufstapels.
public Throwable fillInStackTrace() - Füllt die Stapelverfolgung dieses Throwable-Objekts mit der aktuellen Stapelverfolgung und fügt alle vorherigen Informationen in der Stapelverfolgung hinzu.
Im Folgenden finden Sie den Beispielcode, der einige der oben aufgeführten Methoden verwendet.
(ns clojure.examples.example
(:gen-class))
(defn Example []
(try
(def string1 (slurp "Example.txt"))
(println string1)
(catch java.io.FileNotFoundException e (println (str "caught file
exception: " (.toString e))))
(catch Exception e (println (str "caught exception: " (.toString e))))
(finally (println "This is our final block")))
(println "Let's move on"))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
caught file exception: java.io.FileNotFoundException: Example.txt (No such file
or directory)
This is our final block
Let's move on
Sequences werden mit Hilfe der erstellt ‘seq’Befehl. Das Folgende ist ein einfaches Beispiel für eine Sequenzerstellung.
(ns clojure.examples.example
(:gen-class))
;; This program displays Hello World
(defn Example []
(println (seq [1 2 3])))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
(1 2 3)
Im Folgenden sind die verschiedenen Methoden aufgeführt, die für Sequenzen verfügbar sind.
Sr.Nr. | Methoden & Beschreibung |
---|---|
1 | Nachteile Gibt eine neue Sequenz zurück, wobei 'x' das erste Element und 'seq' der Rest ist. |
2 | konj Gibt eine neue Sequenz zurück, wobei 'x' das Element ist, das am Ende der Sequenz hinzugefügt wird. |
3 | concat Dies wird verwendet, um zwei Sequenzen miteinander zu verknüpfen. |
4 | deutlich Wird verwendet, um nur sicherzustellen, dass der Sequenz unterschiedliche Elemente hinzugefügt werden. |
5 | umkehren Kehrt die Elemente in der Reihenfolge um. |
6 | zuerst Gibt das erste Element der Sequenz zurück. |
7 | zuletzt Gibt das letzte Element der Sequenz zurück. |
8 | sich ausruhen Gibt die gesamte Sequenz mit Ausnahme des ersten Elements zurück. |
9 | Sortieren Gibt eine sortierte Folge von Elementen zurück. |
10 | fallen Löscht Elemente aus einer Sequenz basierend auf der Anzahl der Elemente, die entfernt werden müssen. |
11 | Take-Last Nimmt die letzte Liste der Elemente aus der Sequenz. |
12 | nehmen Nimmt die erste Liste von Elementen aus der Sequenz. |
13 | aufgeteilt Teilt die Reihenfolge der Elemente in zwei Teile. Es wird ein Ort angegeben, an dem die Aufteilung erfolgen soll. |
EIN regular expressionist ein Muster, mit dem Teilzeichenfolgen im Text gefunden werden. Reguläre Ausdrücke werden in einer Vielzahl von Programmiersprachen verwendet und häufig in Programmiersprachen vom Typ LISP verwendet.
Das Folgende ist ein Beispiel für einen regulären Ausdruck.
//d+
Der obige reguläre Ausdruck wird verwendet, um ein weiteres Vorkommen einer Ziffer in einer Zeichenfolge zu finden. Die // Zeichen werden verwendet, um sicherzustellen, dass die Zeichen 'd' und '+' verwendet werden, um einen regulären Ausdruck darzustellen.
Im Allgemeinen funktionieren reguläre Ausdrücke mit den folgenden Regeln.
Es gibt zwei spezielle Positionszeichen, die den Anfang und das Ende einer Zeile kennzeichnen: Caret (∧) und Dollarzeichen ($):
Reguläre Ausdrücke können auch Quantifizierer enthalten. Das Pluszeichen (+) steht für ein oder mehrere Male, angewendet auf das vorhergehende Element des Ausdrucks. Das Sternchen (*) wird verwendet, um null oder mehr Vorkommen darzustellen. Das Fragezeichen (?) Bezeichnet Null oder einmal.
Das Metazeichen {und} wird verwendet, um einer bestimmten Anzahl von Instanzen des vorhergehenden Zeichens zu entsprechen.
In einem regulären Ausdruck kann das Punktsymbol (.) Ein beliebiges Zeichen darstellen. Dies wird als Platzhalterzeichen bezeichnet.
Ein regulärer Ausdruck kann Zeichenklassen enthalten. Eine Reihe von Zeichen kann als einfache Folge von Zeichen angegeben werden, die in den Metazeichen [und] wie in [aeiou] enthalten sind. Für Buchstaben- oder Zahlenbereiche können Sie ein Strich-Trennzeichen wie in [a - z] oder [a - mA - M] verwenden. Das Komplement einer Zeichenklasse wird durch ein führendes Caret in den eckigen Klammern wie in [∧a - z] angegeben und repräsentiert alle Zeichen außer den angegebenen.
Die folgenden Methoden stehen für reguläre Ausdrücke zur Verfügung.
Sr.Nr. | Methoden & Beschreibung |
---|---|
1 | neu strukturieren Gibt eine Instanz von java.util.regex.Pattern zurück. Dies wird dann in weiteren Verfahren zum Mustervergleich verwendet. |
2 | wiederfinden Gibt unter Verwendung von java.util.regex.Matcher.find () die nächste Regex-Übereinstimmung von Zeichenfolge zu Muster zurück. |
3 | ersetzen Die Ersetzungsfunktion wird verwendet, um eine Teilzeichenfolge in einer Zeichenfolge durch einen neuen Zeichenfolgenwert zu ersetzen. Die Suche nach dem Teilstring erfolgt unter Verwendung eines Musters. |
4 | zuerst ersetzen Die Ersetzungsfunktion wird verwendet, um eine Teilzeichenfolge in einer Zeichenfolge durch einen neuen Zeichenfolgenwert zu ersetzen, jedoch nur beim ersten Auftreten der Teilzeichenfolge. Die Suche nach dem Teilstring erfolgt unter Verwendung eines Musters. |
Predicatessind Funktionen, die eine Bedingung auswerten und den Wert true oder false liefern. Wir haben Prädikatfunktionen in den Beispielen des Kapitels über Zahlen gesehen. Wir haben Funktionen wie "gerade?" Was wird verwendet, um zu testen, ob eine Zahl gerade ist oder nicht, oder 'neg?' Hiermit wird getestet, ob eine Zahl größer als Null ist oder nicht. Alle diese Funktionen geben entweder einen wahren oder einen falschen Wert zurück.
Das Folgende ist ein Beispiel für Prädikate in Clojure.
(ns clojure.examples.example
(:gen-class))
;; This program displays Hello World
(defn Example []
(def x (even? 0))
(println x)
(def x (neg? 2))
(println x)
(def x (odd? 3))
(println x)
(def x (pos? 3))
(println x))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
true
false
true
true
Zusätzlich zu den normalen Prädikatfunktionen bietet Clojure weitere Funktionen für Prädikate. Die folgenden Methoden stehen für Prädikate zur Verfügung.
Sr.Nr. | Methoden & Beschreibung |
---|---|
1 | Every-Pred Nimmt eine Reihe von Prädikaten und gibt eine Funktion 'f' zurück, die true zurückgibt, wenn alle zusammengesetzten Prädikate einen logischen true-Wert für alle Argumente zurückgeben, andernfalls false. |
2 | jeder? Gibt true zurück, wenn das Prädikat für jeden Wert true ist, andernfalls false. |
3 | etwas Gibt den ersten logischen wahren Wert für einen Prädikatwert von x in der Auflistung von Werten zurück. |
4 | keine? Gibt false zurück, wenn eines der Prädikate der Werte in einer Sammlung logisch true ist, andernfalls true. |
Destructuring ist eine Funktionalität in Clojure, mit der man Werte aus einer Datenstruktur wie einem Vektor extrahieren und an Symbole binden kann, ohne die Datenstruktur explizit durchlaufen zu müssen.
Schauen wir uns ein Beispiel an, was genau Destrukturierung bedeutet und wie dies geschieht.
Beispiel
(ns clojure.examples.example
(:gen-class))
(defn Example []
(def my-vector [1 2 3 4])
(let [[a b c d] my-vector]
(println a b c d)))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
Ausgabe
1 2 3 4
Im obigen Beispiel sind folgende Dinge zu beachten:
Wir definieren einen Vektor von ganzen Zahlen als 1, 2, 3 und 4.
Wir benutzen dann die ‘let’ Anweisung zum direkten Zuweisen von 4 Variablen (a, b, c und d) zur my-vector-Variablen.
Wenn wir das laufen lassen ‘println’ Aussage zu den vier Variablen können wir sehen, dass sie bereits den Werten im Vektor zugeordnet wurden.
Daher hat clojure die Variable my-vector zerstört, die vier Werte hat, als sie mit der Anweisung 'let' zugewiesen wurde. Die dekonstruierten vier Werte wurden dann den vier Parametern entsprechend zugeordnet.
Wenn es überschüssige Variablen gibt, die keinen entsprechenden Wert haben, dem sie zugewiesen werden können, wird ihnen der Wert Null zugewiesen. Das folgende Beispiel macht diesen Punkt deutlich.
Beispiel
(ns clojure.examples.hello
(:gen-class))
(defn Example []
(def my-vector [1 2 3 4])
(let [[a b c d e] my-vector]
(println a b c d e)))
(Example)
Das obige Programm erzeugt die folgende Ausgabe. Sie können der Ausgabe entnehmen, dass die letzte Variable 'e', da sie keinen entsprechenden Wert im Vektor hat, Null ausmacht.
Ausgabe
1 2 3 4 nil
der Rest
Die Variable 'the-rest' wird verwendet, um die verbleibenden Werte zu speichern, die keiner Variablen zugewiesen werden können.
Ein Beispiel für die Verwendung wird im folgenden Programm gezeigt.
Beispiel
(ns clojure.examples.example
(:gen-class))
(defn Example []
(def my-vector [1 2 3 4])
(let [[a b & the-rest] my-vector]
(println a b the-rest)))
(Example)
Das obige Programm erzeugt die folgende Ausgabe. An der Ausgabe können Sie deutlich erkennen, dass die Werte 3 und 4 keiner Variablen zugewiesen werden können, sodass sie der Variablen 'the-rest' zugewiesen werden.
Ausgabe
1 2 (3 4)
Karten zerstören
Karten können ebenso wie Vektoren zerstört werden. Das Folgende ist ein Beispiel dafür, wie dies erreicht werden kann.
Beispiel
(ns clojure.examples.example
(:gen-class))
(defn Example []
(def my-map {"a" 1 "b" 2})
(let [{a "a" b "b"} my-map]
(println a b)))
(Example)
Das obige Programm erzeugt die folgende Ausgabe. Aus dem Programm können Sie deutlich erkennen, dass die Kartenwerte von „a“ und „b“ den Variablen von a und b zugeordnet sind.
Ausgabe
1 2
In ähnlicher Weise wird der Variablen im Fall von Vektoren ein Wert von Null zugewiesen, wenn bei der Destrukturierung kein entsprechender Wert in der Karte vorhanden ist.
Es folgt ein Beispiel.
Beispiel
(ns clojure.examples.example
(:gen-class))
(defn Example []
(def my-map {"a" 1 "b" 2})
(let [{a "a" b "b" c "c"} my-map]
(println a b c)))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
Ausgabe
1 2 nil
Da das Clojure-Framework von Java-Klassen abgeleitet ist, können die in Java in Clojure verfügbaren Datums- und Uhrzeitklassen verwendet werden. Dasclass date repräsentiert einen bestimmten Zeitpunkt mit Millisekundengenauigkeit.
Im Folgenden sind die für die Datums- / Zeitklasse verfügbaren Methoden aufgeführt.
java.util.Date
Dies wird verwendet, um das Datumsobjekt in Clojure zu erstellen.
Syntax
Es folgt die Syntax.
java.util.Date.
Parameters - Keine.
Return Value - Ordnet ein Datumsobjekt zu und initialisiert es so, dass es den Zeitpunkt darstellt, zu dem es zugewiesen wurde, gemessen auf die nächste Millisekunde.
Beispiel
Ein Beispiel für die Verwendung wird im folgenden Programm gezeigt.
(ns example)
(defn Example []
(def date (.toString (java.util.Date.)))
(println date))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe. Dies hängt vom aktuellen Datum und der aktuellen Uhrzeit auf dem System ab, auf dem das Programm ausgeführt wird.
Tue Mar 01 06:11:17 UTC 2016
java.text.SimpleDateFormat
Dies wird verwendet, um die Datumsausgabe zu formatieren.
Syntax
Es folgt die Syntax.
(java.text.SimpleDateFormat. format dt)
Parameters- 'Format' ist das Format, das beim Formatieren des Datums verwendet wird. 'dt' ist das Datum, das formatiert werden muss.
Return Value - Eine formatierte Datumsausgabe.
Beispiel
Ein Beispiel für die Verwendung wird im folgenden Programm gezeigt.
(ns example)
(defn Example []
(def date (.format (java.text.SimpleDateFormat. "MM/dd/yyyy") (new java.util.Date)))
(println date))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe. Dies hängt vom aktuellen Datum und der aktuellen Uhrzeit auf dem System ab, auf dem das Programm ausgeführt wird.
03/01/2016
Zeit bekommen
Gibt die Anzahl der Millisekunden seit dem 1. Januar 1970, 00:00:00 GMT zurück, die durch dieses Datumsobjekt dargestellt werden.
Syntax
Es folgt die Syntax.
(.getTime)
Parameters - Keine.
Return Value - Die Anzahl der Millisekunden seit dem 1. Januar 1970, 00:00:00 GMT, dargestellt durch dieses Datum.
Beispiel
Ein Beispiel für die Verwendung wird im folgenden Programm gezeigt.
(ns example)
(import java.util.Date)
(defn Example []
(def date (.getTime (java.util.Date.)))
(println date))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe. Dies hängt vom aktuellen Datum und der aktuellen Uhrzeit auf dem System ab, auf dem das Programm ausgeführt wird.
1456812778160
Atomssind ein Datentyp in Clojure, mit dem ein gemeinsamer, synchroner und unabhängiger Status verwaltet werden kann. Ein Atom ist wie jeder Referenztyp in einer anderen Programmiersprache. Die Hauptverwendung eines Atoms besteht darin, die unveränderlichen Datenstrukturen von Clojure zu speichern. Der Wert eines Atoms wird mit dem geändertswap! method.
Intern tauschen! Liest den aktuellen Wert, wendet die Funktion darauf an und versucht, ihn zu vergleichen und einzustellen. Da ein anderer Thread den Wert in der Zwischenzeit möglicherweise geändert hat, muss er möglicherweise erneut versuchen, und zwar in einer Spin-Schleife. Der Nettoeffekt besteht darin, dass der Wert immer das Ergebnis der atomaren Anwendung der bereitgestellten Funktion auf einen aktuellen Wert ist.
Beispiel
Atome werden mit Hilfe der Atommethode erzeugt. Ein Beispiel dafür finden Sie im folgenden Programm.
(ns clojure.examples.example
(:gen-class))
(defn example []
(def myatom (atom 1))
(println @myatom))
(example)
Ausgabe
Das obige Programm erzeugt das folgende Ergebnis.
1
Auf den Wert von atom wird mit dem @ -Symbol zugegriffen. Clojure hat einige Operationen, die an Atomen durchgeführt werden können. Es folgen die Operationen.
Sr.Nr. | Operationen & Beschreibung |
---|---|
1 | zurücksetzen! Setzt den Wert von atom ohne Berücksichtigung des aktuellen Werts auf einen neuen Wert. |
2 | vergleichen und einstellen! Setzt den Wert von Atom genau dann atomar auf den neuen Wert, wenn der aktuelle Wert des Atoms mit dem alten Wert des Atoms identisch ist. Gibt true zurück, wenn set auftritt, andernfalls false. |
3 | Tauschen! Vertauscht den Wert des Atoms atomar gegen einen neuen, basierend auf einer bestimmten Funktion. |
In Clojure, metadatawird verwendet, um die Daten in einer Sammlung oder die in einem Symbol gespeicherten Daten mit Anmerkungen zu versehen. Dies wird normalerweise verwendet, um Daten über Typen mit dem zugrunde liegenden Compiler zu versehen, kann aber auch für Entwickler verwendet werden. Metadaten werden nicht als Teil des Wertes des Objekts betrachtet. Gleichzeitig sind Metadaten unveränderlich.
Die folgenden Operationen sind in Clojure in Bezug auf Metadaten möglich.
Sr.Nr. | Operationen & Beschreibung |
---|---|
1 | Meta-mit Diese Funktion wird verwendet, um eine Metadatenzuordnung für jedes Objekt zu definieren. |
2 | Meta Diese Funktion wird verwendet, um festzustellen, ob einem Objekt Metadaten zugeordnet sind. |
3 | variieren-meta Gibt ein Objekt des gleichen Typs und Werts wie das ursprüngliche Objekt zurück, jedoch mit kombinierten Metadaten. |
StructMapswerden zum Erstellen von Strukturen in Clojure verwendet. Wenn Sie beispielsweise eine Struktur erstellen möchten, die aus einem Mitarbeiternamen und einer Mitarbeiter-ID besteht, können Sie dies mit StructMaps tun.
Die folgenden Operationen sind in Clojure in Bezug auf StructMaps möglich.
Sr.Nr. | Operationen & Beschreibung |
---|---|
1 | defstruct Diese Funktion dient zur Definition der erforderlichen Struktur. |
2 | struct Mit dieser Funktion wird ein Strukturobjekt des Typs definiert, das durch die Defstruct-Operation erstellt wird. |
3 | Struktur-Map Diese Funktion wird verwendet, um Schlüsselwerten spezifisch Werte zuzuweisen, indem explizit definiert wird, welche Werte welchen Schlüsseln in der Struktur zugewiesen werden. |
4 | Zugriff auf einzelne Felder Auf einzelne Felder der Struktur kann zugegriffen werden, indem auf die Schlüssel zusammen mit dem Strukturobjekt zugegriffen wird. |
5 | Unveränderliche Natur Standardmäßig sind Strukturen auch unveränderlich. Wenn wir also versuchen, den Wert eines bestimmten Schlüssels zu ändern, ändert sich dieser nicht. |
6 | Hinzufügen eines neuen Schlüssels zur Struktur Da Strukturen unveränderlich sind, kann der Struktur nur durch Erstellen einer neuen Struktur ein weiterer Schlüssel hinzugefügt werden. Ein Beispiel dafür, wie dies erreicht werden kann, zeigt das folgende Programm. |
Wie bereits mehrfach erwähnt, ist Clojure eine Programmiersprache, in der viele der Datentypen unveränderlich sind. Dies bedeutet, dass der Wert einer Variablen nur geändert werden kann, indem eine neue Variable erstellt und ihr der neue Wert zugewiesen wird. Clojure bietet jedoch einige Elemente, die einen veränderlichen Zustand erzeugen können. Wir haben gesehen, dass dies mit dem Atomdatentyp erreicht werden kann. Dies kann auch über Agenten erreicht werden.
Agentsbieten unabhängige, asynchrone Änderung einzelner Standorte. Agenten sind während ihrer gesamten Lebensdauer an einen einzelnen Speicherort gebunden und erlauben nur die Mutation dieses Speicherorts (in einen neuen Status) als Ergebnis einer Aktion. Aktionen sind Funktionen (mit optional zusätzlichen Argumenten), die asynchron auf den Status eines Agenten angewendet werden und deren Rückgabewert zum neuen Status des Agenten wird.
Die folgenden Operationen sind in Clojure in Bezug auf Agenten möglich.
Sr.Nr. | Operationen & Beschreibung |
---|---|
1 | Agent Ein Agent wird mit dem Befehl agent erstellt. |
2 | senden Diese Funktion wird verwendet, um einen Wert an den Agenten zu senden. |
3 | Shutdown-Agenten Diese Funktion wird verwendet, um laufende Agenten herunterzufahren. |
4 | abschicken Es gibt Fälle, in denen einem Agenten eine Funktion zugewiesen wird, die von Natur aus blockiert. |
5 | warten auf Da es eine Verzögerung gibt, wenn ein Wert eines Agenten aktualisiert wird, hat Clojure eine Funktion zum Warten bereitgestellt, mit der die Zeit in Millisekunden angegeben wird, um auf die Aktualisierung des Agenten zu warten. |
6 | erwarten Blockiert den aktuellen Thread (auf unbestimmte Zeit!), Bis alle bisher von diesem Thread oder Agenten an die Agenten gesendeten Aktionen ausgeführt wurden. Blockiert fehlgeschlagene Agenten. |
7 | Agentenfehler Gibt die Ausnahme zurück, die während einer asynchronen Aktion des Agenten ausgelöst wird, wenn der Agent ausfällt. Gibt null zurück, wenn der Agent nicht fehlschlägt. |
Watcherssind Funktionen, die Variablentypen wie Atomen und Referenzvariablen hinzugefügt werden und aufgerufen werden, wenn sich ein Wert des Variablentyps ändert. Wenn das aufrufende Programm beispielsweise den Wert einer Atomvariablen ändert und eine Überwachungsfunktion an die Atomvariable angehängt ist, wird die Funktion aufgerufen, sobald der Wert des Atoms geändert wird.
Die folgenden Funktionen sind in Clojure for Watchers verfügbar.
Add-Watch
Fügt einer Agent / Atom / Var / Ref-Referenz eine Überwachungsfunktion hinzu. Die Uhr‘fn’muss ein 'fn' von 4 Argumenten sein: ein Schlüssel, die Referenz, sein alter Zustand, sein neuer Zustand. Wann immer der Status der Referenz geändert wurde, werden die Funktionen registrierter Uhren aufgerufen.
Syntax
Es folgt die Syntax.
(add-watch variable :watcher
(fn [key variable-type old-state new-state]))
Parameters- 'Variable' ist der Name des Atoms oder der Referenzvariablen. 'Variablentyp' ist der Variablentyp, entweder Atom- oder Referenzvariable. 'alter Zustand & neuer Zustand' sind Parameter, die automatisch den alten und den neuen Wert der Variablen enthalten. 'key' muss pro Referenz eindeutig sein und kann verwendet werden, um die Uhr mit remove-watch zu entfernen.
Return Value - Keine.
Beispiel
Ein Beispiel für die Verwendung wird im folgenden Programm gezeigt.
(ns clojure.examples.example
(:gen-class))
(defn Example []
(def x (atom 0))
(add-watch x :watcher
(fn [key atom old-state new-state]
(println "The value of the atom has been changed")
(println "old-state" old-state)
(println "new-state" new-state)))
(reset! x 2))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
The value of the atom has been changed
old-state 0
new-state 2
Uhr entfernen
Entfernt eine Uhr, die an eine Referenzvariable angehängt wurde.
Syntax
Es folgt die Syntax.
(remove-watch variable watchname)
Parameters- 'Variable' ist der Name des Atoms oder der Referenzvariablen. 'watchname' ist der Name, der der Uhr gegeben wird, wenn die Uhrfunktion definiert wird.
Return Value - Keine.
Beispiel
Ein Beispiel für die Verwendung wird im folgenden Programm gezeigt.
(ns clojure.examples.example
(:gen-class))
(defn Example []
(def x (atom 0))
(add-watch x :watcher
(fn [key atom old-state new-state]
(println "The value of the atom has been changed")
(println "old-state" old-state)
(println "new-state" new-state)))
(reset! x 2)
(remove-watch x :watcher)
(reset! x 4))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
The value of the atom has been changed
old-state 0
new-state 2
Aus dem obigen Programm können Sie deutlich erkennen, dass der zweite Rücksetzbefehl den Watcher nicht auslöst, da er aus der Watcher-Liste entfernt wurde.
In jeder Sprache, Macroswerden verwendet, um Inline-Code zu generieren. Clojure ist keine Ausnahme und bietet Entwicklern einfache Makrofunktionen. Makros werden zum Schreiben von Routinen zur Codegenerierung verwendet, die dem Entwickler eine leistungsstarke Möglichkeit bieten, die Sprache an die Anforderungen des Entwicklers anzupassen.
Im Folgenden sind die für Makros verfügbaren Methoden aufgeführt.
defmacro
Diese Funktion wird verwendet, um Ihr Makro zu definieren. Das Makro hat einen Makronamen, eine Parameterliste und den Hauptteil des Makros.
Syntax
Es folgt die Syntax.
(defmacro name [params*] body)
Parameters- 'name' ist der Name des Makros. 'params' sind die dem Makro zugewiesenen Parameter. 'body' ist der Body des Makros.
Return Value - Keine.
Beispiel
Ein Beispiel für die Verwendung wird im folgenden Programm gezeigt.
(ns clojure.examples.example
(:gen-class))
(defn Example []
(defmacro Simple []
(println "Hello"))
(macroexpand '(Simple)))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
Hello
Aus dem obigen Programm können Sie erkennen, dass das Makro 'Einfach' inline zu 'println' "Hallo" erweitert wurde. Makros ähneln Funktionen, mit dem einzigen Unterschied, dass die Argumente für ein Formular bei Makros ausgewertet werden.
Makro erweitern
Dies wird verwendet, um ein Makro zu erweitern und den Code in das Programm einzufügen.
Syntax
Es folgt die Syntax.
(macroexpand macroname)
Parameters - 'Makroname' ist der Name des Makros, das erweitert werden muss.
Return Value - Das erweiterte Makro.
Beispiel
Ein Beispiel für die Verwendung wird im folgenden Programm gezeigt.
(ns clojure.examples.example
(:gen-class))
(defn Example []
(defmacro Simple []
(println "Hello"))
(macroexpand '(Simple)))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
Hello
Makro mit Argumenten
Makros können auch verwendet werden, um Argumente aufzunehmen. Das Makro kann beliebig viele Argumente aufnehmen. Das folgende Beispiel zeigt, wie Argumente verwendet werden können.
Beispiel
(ns clojure.examples.example
(:gen-class))
(defn Example []
(defmacro Simple [arg]
(list 2 arg))
(println (macroexpand '(Simple 2))))
(Example)
Im obigen Beispiel wird ein Argument in das einfache Makro eingefügt und das Argument dann verwendet, um einer Liste einen Argumentwert hinzuzufügen.
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
(2 2)
Reference valuessind eine andere Möglichkeit, wie Clojure mit der Forderung nach veränderlichen Variablen arbeiten kann. Clojure bietet veränderbare Datentypen wie Atome, Agenten und Referenztypen.
Im Folgenden sind die Operationen aufgeführt, die für Referenzwerte verfügbar sind.
Sr.Nr. | Operationen & Beschreibung |
---|---|
1 | ref Dies wird verwendet, um einen Referenzwert zu erstellen. Beim Erstellen eines Referenzwerts besteht die Möglichkeit, eine Validierungsfunktion bereitzustellen, mit der der erstellte Wert validiert wird. |
2 | neu einstellen Mit dieser Funktion wird der Wert einer Referenz auf einen neuen Wert gesetzt, unabhängig davon, welcher Wert älter ist. |
3 | ändern Diese Funktion wird verwendet, um den Wert eines Referenztyps auf sichere Weise zu ändern. Dies wird in einem Thread ausgeführt, auf den kein anderer Prozess zugreifen kann. |
4 | dosync Führt den Ausdruck (implizit) in einer Transaktion aus, die den Ausdruck und alle verschachtelten Aufrufe umfasst. |
5 | pendeln Commute wird auch verwendet, um den Wert eines Referenztyps zu ändern, genau wie alter und ref-set. |
Um die Datenbankfunktionalität nutzen zu können, müssen Sie zuerst die herunterladen jdbc files von der folgenden URL - https://codeload.github.com/clojure/java.jdbc/zip/master
Sie finden eine Zip-Datei mit den erforderlichen Treibern, damit Clojure eine Verbindung zu Datenbanken herstellen kann. Stellen Sie nach dem Extrahieren der Zip-Datei sicher, dass Sie den entpackten Speicherort zu Ihrem Klassenpfad hinzufügen.
Die Hauptdatei für die Datenbankkonnektivität ist eine Datei mit dem Namen jdbc.clj in der Location Clojure / Java.
Der Clojure JDBC-Connector unterstützt eine Vielzahl von Datenbanken, von denen einige die folgenden sind.
- H2Database
- Oracle
- Microsoft SQL Server
- MySQL
- PostgreSQL
In unserem Beispiel verwenden wir MySQL DB als Beispiel.
Die folgenden Operationen sind in Clojure in Bezug auf Datenbanken möglich.
Datenbankverbindung
Stellen Sie vor dem Herstellen einer Verbindung zu einer MySQL-Datenbank Folgendes sicher:
Sie haben eine Datenbank TESTDB erstellt.
Sie haben in TESTDB eine Tabelle EMPLOYEE erstellt.
Diese Tabelle enthält die Felder FIRST_NAME, LAST_NAME, AGE, SEX und INCOME.
Die Benutzer-ID "testuser" und das Kennwort "test123" sind für den Zugriff auf TESTDB festgelegt.
Stellen Sie sicher, dass Sie die 'MySQL-JAR-Datei' heruntergeladen und die Datei Ihrem Klassenpfad hinzugefügt haben.
Sie haben das MySQL-Tutorial durchgearbeitet, um die MySQL-Grundlagen zu verstehen .
Syntax
Im Folgenden finden Sie die Syntax zum Erstellen einer Verbindung in Clojure.
(def connection_name {
:subprotocol “protocol_name”
:subname “Location of mysql DB”
:user “username” :password “password” })
Parameters- 'Verbindungsname' ist der Name, der der Verbindung gegeben werden soll. 'Unterprotokoll' ist das Protokoll, das für die Verbindung verwendet werden soll. Standardmäßig verwenden wir das MySQL-Protokoll. 'subname' ist die URL, über die zusammen mit dem Datenbanknamen eine Verbindung zur MySQL-Datenbank hergestellt werden soll. 'Benutzer' ist der Benutzername, mit dem eine Verbindung zur Datenbank hergestellt wird. 'Passwort' ist das Passwort, mit dem eine Verbindung zur Datenbank hergestellt wird.
Return Value - Dadurch wird eine Verbindungszeichenfolge bereitgestellt, die in nachfolgenden MySQL-Operationen verwendet werden kann.
Das folgende Beispiel zeigt, wie Sie eine Verbindung zu den Tabellen im Informationsschema herstellen und alle Daten in der Tabelle abrufen.
Beispiel
(ns test.core
(:require [clojure.java.jdbc :as sql]))
(defn -main []
(def mysql-db {
:subprotocol "mysql"
:subname "//127.0.0.1:3306/information_schema"
:user "root"
:password "shakinstev"})
(println (sql/query mysql-db
["select table_name from tables"]
:row-fn :table_name)))
Daten abfragen
Das Abfragen von Daten in einer beliebigen Datenbank bedeutet, einige nützliche Informationen aus der Datenbank abzurufen. Sobald eine Datenbankverbindung hergestellt ist, können Sie eine Abfrage in dieser Datenbank durchführen. Es folgt die Syntax, mit der Daten mit Clojure abgefragt werden können.
Syntax
clojure.java.jdbc/query dbconn
["query"]
:row-fn :sequence
Parameters- 'dbconn' ist der Name der Verbindung, über die eine Verbindung zur Datenbank hergestellt wird. 'query' ist die Abfragezeichenfolge, mit der Daten aus der Datenbank abgerufen werden. ': sequence' umfasst standardmäßig alle aus der Datenbank abgerufenen Datenzeilen und wird als Sequenz zurückgegeben. Die erforderlichen Operationen an der Sequenz können dann ausgeführt werden, um zu sehen, welche Daten abgerufen wurden.
Return Value - Dies gibt eine Sequenz zurück, die die Datenzeilen der Abfrageoperation enthält.
Das folgende Beispiel zeigt, wie Sie eine Verbindung zur Mitarbeitertabelle herstellen und die Spalte Vorname der Zeilen in der Tabelle abrufen.
Beispiel
(ns test.core
(:require [clojure.java.jdbc :as sql]))
(defn -main []
(def mysql-db {
:subprotocol "mysql"
:subname "//127.0.0.1:3306/testdb"
:user "root"
:password "shakinstev"})
(println (sql/query mysql-db
["select first_name from employee"]
:row-fn :first_name)))
Aus dem obigen Code können wir das sehen
Die Abfrage "Vorname vom Mitarbeiter auswählen" wird als Abfragezeichenfolge übergeben.
Der: first_name ist die Sequenz, die als Ergebnis der Abrufoperation zurückgegeben wird.
Wenn wir davon ausgehen, dass unsere Datenbank nur eine Zeile enthält, die den Wert first_name von John enthält, folgt die Ausgabe des obigen Programms.
(John)
Daten einfügen
Dies ist erforderlich, wenn Sie Ihre Datensätze in einer Datenbanktabelle erstellen möchten. Es folgt die Syntax, mit der Daten mit Clojure eingefügt werden können. Dies geschieht mit dem‘insert!’ Funktion.
Syntax
clojure.java.jdbc/insert!
:table_name {:column_namen columnvalue}
Parameters- ': table_name' ist der Name der Tabelle, in die eingefügt werden muss. '{: column_namen columnvalue}' ist eine Zuordnung aller Spaltennamen und -werte, die als Zeile in die Tabelle eingefügt werden müssen.
Return Value - Dies gibt null zurück, wenn das Einfügen erfolgreich durchgeführt wurde.
Das folgende Beispiel zeigt, wie ein Datensatz in die Mitarbeitertabelle in der testdb-Datenbank eingefügt wird.
Beispiel
(ns test.core
(:require [clojure.java.jdbc :as sql]))
(defn -main []
(def mysql-db {
:subprotocol "mysql"
:subname "//127.0.0.1:3306/testdb"
:user "root"
:password "shakinstev"})
(sql/insert! mysql-db
:employee {:first_name "John" :last_name "Mark" :sex "M" :age 30 :income 30}))
Wenn Sie jetzt Ihre MySQL-Datenbank und die Mitarbeitertabelle überprüfen, werden Sie feststellen, dass die obige Zeile erfolgreich in die Tabelle eingefügt wurde.
Daten löschen
Zeilen können mit der Taste aus einer Tabelle gelöscht werden ‘delete!’Funktion. Im Folgenden finden Sie die Syntax, wie diese Operation ausgeführt werden kann.
Syntax
clojure.java.jdbc/delete!
:table_name [condition]
Parameters- ': table_name' ist der Name der Tabelle, in die eingefügt werden muss. 'Bedingung' ist die Bedingung, mit der bestimmt wird, welche Zeile aus der Tabelle gelöscht werden muss.
Return Value - Dies gibt die Anzahl der gelöschten Zeilen zurück.
Das folgende Beispiel zeigt, wie ein Datensatz aus der Mitarbeitertabelle in der testdb-Datenbank gelöscht wird. In diesem Beispiel wird eine Zeile aus der Tabelle gelöscht, sofern das Alter 30 Jahre beträgt.
Beispiel
(ns test.core
(:require [clojure.java.jdbc :as sql]))
(defn -main []
(def mysql-db {
:subprotocol "mysql"
:subname "//127.0.0.1:3306/testdb"
:user "root"
:password "shakinstev"})
(println (sql/delete! mysql-db
:employee ["age = ? " 30])))
Wenn Sie einen Datensatz mit einer Zeile hatten, deren Alter dem Wert 30 entspricht, wird diese Zeile gelöscht.
Daten aktualisieren
Zeilen können mithilfe der Tabelle aus einer Tabelle aktualisiert werden ‘update!’Funktion. Im Folgenden finden Sie die Syntax, wie diese Operation ausgeführt werden kann.
Syntax
clojure.java.jdbc/update!
:table_name
{setcondition}
[condition]
Parameters- ': table_name' ist der Name der Tabelle, in die eingefügt werden muss. 'setcondition' ist die Spalte, die wie in einer Karte angegeben aktualisiert werden muss. 'Bedingung' ist die Bedingung, mit der bestimmt wird, welche Zeile aus der Tabelle gelöscht werden muss.
Return Value - Dies gibt die Anzahl der aktualisierten Zeilen zurück.
Das folgende Beispiel zeigt, wie ein Datensatz aus der Mitarbeitertabelle in der testdb-Datenbank gelöscht wird. Das Beispiel aktualisiert eine Zeile aus der Tabelle basierend auf der Bedingung, dass das Alter 30 Jahre beträgt, und aktualisiert den Wert des Einkommens auf 40 Jahre.
(ns test.core
(:require [clojure.java.jdbc :as sql]))
(defn -main []
(def mysql-db {
:subprotocol "mysql"
:subname "//127.0.0.1:3306/testdb"
:user "root"
:password "shakinstev"})
(println (sql/update! mysql-db
:employee
{:income 40}
["age = ? " 30])))
Wenn Sie einen Datensatz mit einer Zeile hatten, deren Alter dem Wert 30 entspricht, wird diese Zeile aktualisiert, wobei der Wert des Einkommens auf 40 festgelegt wird.
Transaktionen
Transaktionen sind Mechanismen, die die Datenkonsistenz gewährleisten. Transaktionen haben die folgenden vier Eigenschaften:
Atomicity - Entweder wird eine Transaktion abgeschlossen oder es passiert überhaupt nichts.
Consistency - Eine Transaktion muss in einem konsistenten Zustand beginnen und das System in einem konsistenten Zustand belassen.
Isolation - Zwischenergebnisse einer Transaktion sind außerhalb der aktuellen Transaktion nicht sichtbar.
Durability - Sobald eine Transaktion festgeschrieben wurde, bleiben die Auswirkungen auch nach einem Systemausfall bestehen.
Beispiel
Das folgende Beispiel zeigt, wie Transaktionen in Clojure implementiert werden. Alle Operationen, die in einer Transaktion ausgeführt werden müssen, müssen in die eingebettet werden‘with-dbtransaction’ Klausel.
(ns test.core
(:require [clojure.java.jdbc :as sql]))
(defn -main []
(def mysql-db {
:subprotocol "mysql"
:subname "//127.0.0.1:3306/testdb"
:user "root"
:password "shakinstev"})
(sql/with-db-transaction [t-con mysql-db]
(sql/update! t-con
:employee
{:income 40}
["age = ? " 30])))
Wie wir bereits wissen, wird Clojure-Code am Ende in der virtuellen Java-Umgebung ausgeführt. Daher ist es nur sinnvoll, dass Clojure alle Funktionen von Java nutzen kann. In diesem Kapitel diskutieren wir die Korrelation zwischen Clojure und Java.
Java-Methoden aufrufen
Java-Methoden können mithilfe der Punktnotation aufgerufen werden. Ein Beispiel sind Zeichenfolgen. Da alle Zeichenfolgen in Clojure ohnehin Java-Zeichenfolgen sind, können Sie normale Java-Methoden für Zeichenfolgen aufrufen.
Ein Beispiel dafür finden Sie im folgenden Programm.
Beispiel
(ns Project
(:gen-class))
(defn Example []
(println (.toUpperCase "Hello World")))
(Example)
Das obige Programm erzeugt die folgende Ausgabe. Sie können dem Code entnehmen, dass die Punktnotation für eine beliebige Zeichenfolgenmethode auch in Clojure funktioniert, wenn Sie sie nur aufrufen.
Ausgabe
HELLO WORLD
Java-Methoden mit Parametern aufrufen
Sie können auch Java-Methoden mit Parametern aufrufen. Ein Beispiel dafür finden Sie im folgenden Programm.
Beispiel
(ns Project
(:gen-class))
(defn Example []
(println (.indexOf "Hello World","e")))
(Example)
Das obige Programm erzeugt die folgende Ausgabe. Sie können dem obigen Code entnehmen, dass wir den Parameter "e" an die indexOf-Methode übergeben. Das obige Programm erzeugt die folgende Ausgabe.
Ausgabe
1
Erstellen von Java-Objekten
Objekte können in Clojure mit dem Schlüsselwort 'new' erstellt werden, ähnlich wie in Java.
Ein Beispiel dafür finden Sie im folgenden Programm.
Beispiel
(ns Project
(:gen-class))
(defn Example []
(def str1 (new String "Hello"))
(println str1))
(Example)
Das obige Programm erzeugt die folgende Ausgabe. Sie können dem obigen Code entnehmen, dass wir das Schlüsselwort 'new' verwenden können, um ein neues Objekt aus der vorhandenen String-Klasse aus Java zu erstellen. Wir können den Wert beim Erstellen des Objekts übergeben, genau wie in Java. Das obige Programm erzeugt die folgende Ausgabe.
Ausgabe
Hello
Das folgende Beispiel zeigt, wie wir ein Objekt der Integer-Klasse erstellen und in den normalen Clojure-Befehlen verwenden können.
Beispiel
(ns Project
(:gen-class))
(defn Example []
(def my-int(new Integer 1))
(println (+ 2 my-int)))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
Ausgabe
3
Importbefehl
Wir können den Befehl import auch verwenden, um Java-Bibliotheken in den Namespace aufzunehmen, damit auf die Klassen und Methoden problemlos zugegriffen werden kann.
Das folgende Beispiel zeigt, wie wir den Importbefehl verwenden können. Im Beispiel verwenden wir den Befehl import, um die Klassen aus dem zu importierenjava.util.stackBibliothek. Wir können dann die Push- und Pop-Methode der Stapelklasse so verwenden, wie sie sind.
Beispiel
(ns Project
(:gen-class))
(import java.util.Stack)
(defn Example []
(let [stack (Stack.)]
(.push stack "First Element")
(.push stack "Second Element")
(println (first stack))))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
Ausgabe
First Element
Ausführen von Code mit dem Java-Befehl
Clojure-Code kann mit dem Java-Befehl ausgeführt werden. Im Folgenden finden Sie die Syntax, wie dies durchgeführt werden kann.
java -jar clojure-1.2.0.jar -i main.clj
Sie müssen die Clojure-JAR-Datei erwähnen, damit alle Clojure-basierten Klassen in die JVM geladen werden. Die Datei 'main.clj' ist die Clojure-Codedatei, die ausgeführt werden muss.
Integrierte Java-Funktionen
Clojure kann viele der in Java integrierten Funktionen verwenden. Einige von ihnen sind -
Math PI function- Clojure kann die Math-Methode für den Wert von PI verwenden. Es folgt ein Beispielcode.
Beispiel
(ns Project
(:gen-class))
(defn Example []
(println (. Math PI)))
(Example)
Der obige Code erzeugt die folgende Ausgabe.
Ausgabe
3.141592653589793
System Properties- Clojure kann auch die Systemeigenschaften abfragen. Es folgt ein Beispielcode.
Beispiel
(ns Project
(:gen-class))
(defn Example []
(println (.. System getProperties (get "java.version"))))
(Example)
Abhängig von der Java-Version auf dem System wird der entsprechende Wert angezeigt. Es folgt eine Beispielausgabe.
Ausgabe
1.8.0_45
Bei der Clojure-Programmierung sind die meisten Datentypen unveränderlich. Wenn Sie also gleichzeitig programmieren, ist der Code, der diese Datentypen verwendet, ziemlich sicher, wenn der Code auf mehreren Prozessoren ausgeführt wird. Oft ist es jedoch erforderlich, Daten gemeinsam zu nutzen, und wenn Daten über mehrere Prozessoren hinweg gemeinsam genutzt werden sollen, muss sichergestellt werden, dass der Status der Daten in Bezug auf die Integrität bei der Arbeit mit mehreren Prozessoren erhalten bleibt. Dies ist bekannt alsconcurrent programming und Clojure bietet Unterstützung für eine solche Programmierung.
Das Software-Transaktionsspeichersystem (STM), das durch Dosieren, Ref, Setzen, Ändern usw. verfügbar gemacht wird, unterstützt das synchrone und koordinierte Teilen des sich ändernden Status zwischen Threads. Das Agentensystem unterstützt das asynchrone und unabhängige Teilen des sich ändernden Status zwischen Threads. Das Atomsystem unterstützt das synchrone und unabhängige Teilen des sich ändernden Zustands zwischen Threads. Während das dynamische VAR-System, das durch Def, Bindung usw. verfügbar gemacht wird, das Isolieren des sich ändernden Zustands innerhalb von Threads unterstützt.
Andere Programmiersprachen folgen ebenfalls dem Modell für die gleichzeitige Programmierung.
Sie haben einen direkten Bezug zu den Daten, die geändert werden können.
Wenn ein gemeinsamer Zugriff erforderlich ist, wird das Objekt gesperrt, der Wert geändert und der Prozess für den nächsten Zugriff auf diesen Wert fortgesetzt.
In Clojure gibt es keine Sperren, sondern indirekte Verweise auf unveränderliche persistente Datenstrukturen.
In Clojure gibt es drei Arten von Referenzen.
Vars - Änderungen sind in Threads isoliert.
Refs - Änderungen werden zwischen Threads synchronisiert und koordiniert.
Agents - Beinhaltet asynchrone unabhängige Änderungen zwischen Threads.
Die folgenden Operationen sind in Clojure in Bezug auf die gleichzeitige Programmierung möglich.
Transaktionen
Die Parallelität in Clojure basiert auf Transaktionen. Referenzen können nur innerhalb einer Transaktion geändert werden. Die folgenden Regeln werden bei Transaktionen angewendet.
- Alle Änderungen sind atomar und isoliert.
- Jede Änderung an einer Referenz erfolgt in einer Transaktion.
- Keine Transaktion sieht den Effekt einer anderen Transaktion.
- Alle Transaktionen werden innerhalb des Dosync-Blocks platziert.
Wir haben bereits gesehen, was der Dosync-Block tut. Schauen wir uns das noch einmal an.
dosync
Führt den Ausdruck (implizit) in einer Transaktion aus, die den Ausdruck und alle verschachtelten Aufrufe umfasst. Startet eine Transaktion, wenn in diesem Thread noch keine ausgeführt wird. Jede nicht erfasste Ausnahme bricht die Transaktion ab und fließt aus der Dosync heraus.
Es folgt die Syntax.
Syntax
(dosync expression)
Parameters - 'Ausdruck' ist die Menge der Ausdrücke, die im Dosync-Block enthalten sind.
Return Value - Keine.
Schauen wir uns ein Beispiel an, in dem wir versuchen, den Wert einer Referenzvariablen zu ändern.
Beispiel
(ns clojure.examples.example
(:gen-class))
(defn Example []
(def names (ref []))
(alter names conj "Mark"))
(Example)
Ausgabe
Das obige Programm gibt beim Ausführen den folgenden Fehler aus.
Caused by: java.lang.IllegalStateException: No transaction running
at clojure.lang.LockingTransaction.getEx(LockingTransaction.java:208)
at clojure.lang.Ref.alter(Ref.java:173)
at clojure.core$alter.doInvoke(core.clj:1866)
at clojure.lang.RestFn.invoke(RestFn.java:443)
at clojure.examples.example$Example.invoke(main.clj:5) at clojure.examples.example$eval8.invoke(main.clj:7)
at clojure.lang.Compiler.eval(Compiler.java:5424)
... 12 more
Anhand des Fehlers können Sie deutlich erkennen, dass Sie den Wert eines Referenztyps nicht ändern können, ohne zuvor eine Transaktion initiiert zu haben.
Damit der obige Code funktioniert, müssen wir den Befehl alter in einen Dosync-Block einfügen, wie im folgenden Programm beschrieben.
Beispiel
(ns clojure.examples.example
(:gen-class))
(defn Example []
(def names (ref []))
(defn change [newname]
(dosync
(alter names conj newname)))
(change "John")
(change "Mark")
(println @names))
(Example)
Das obige Programm erzeugt die folgende Ausgabe.
Ausgabe
[John Mark]
Sehen wir uns ein weiteres Beispiel für Dosync an.
Beispiel
(ns clojure.examples.example
(:gen-class))
(defn Example []
(def var1 (ref 10))
(def var2 (ref 20))
(println @var1 @var2)
(defn change-value [var1 var2 newvalue]
(dosync
(alter var1 - newvalue)
(alter var2 + newvalue)))
(change-value var1 var2 20)
(println @var1 @var2))
(Example)
Im obigen Beispiel haben wir zwei Werte, die in einem Dosync-Block geändert werden. Wenn die Transaktion erfolgreich ist, ändern sich beide Werte, andernfalls schlägt die gesamte Transaktion fehl.
Das obige Programm erzeugt die folgende Ausgabe.
Ausgabe
10 20
-10 40
Clojure hat einige Bibliotheken beigesteuert, die die Möglichkeit zum Erstellen haben Desktop und Web-based applications. Lassen Sie uns jeden einzelnen von ihnen diskutieren.
Sr.Nr. | Anwendungen & Beschreibung |
---|---|
1 | Desktop - Wippe See-saw ist eine Bibliothek, mit der Desktop-Anwendungen erstellt werden können. |
2 | Desktop - Ändern des Textwerts Der Wert des Inhalts im Fenster kann mithilfe von geändert werden ‘config!’Möglichkeit. Im folgenden Beispiel wird die Konfiguration! Mit dieser Option wird der Fensterinhalt auf den neuen Wert "Auf Wiedersehen" geändert. |
3 | Desktop - Anzeigen eines modalen Dialogfelds Ein modales Dialogfeld kann mithilfe der Alarmmethode der Wippe-Klasse angezeigt werden. Die Methode verwendet den Textwert, der im modalen Dialogfeld angezeigt werden muss. |
4 | Desktop - Anzeigen von Schaltflächen Schaltflächen können mit Hilfe der Schaltflächenklasse angezeigt werden. |
5 | Desktop - Beschriftungen anzeigen Beschriftungen können mit Hilfe der Beschriftungsklasse angezeigt werden. |
6 | Desktop - Anzeigen von Textfeldern Textfelder können mit Hilfe der Textklasse angezeigt werden. |
Webanwendungen - Einführung
Um eine Webanwendung in Clojure zu erstellen, müssen Sie die Ring-Anwendungsbibliothek verwenden, die unter dem folgenden Link verfügbar ist https://github.com/ring-clojure/ring
Sie müssen sicherstellen, dass Sie die erforderlichen Gläser von der Site herunterladen und als Abhängigkeit für die Clojure-Anwendung hinzufügen.
Das Ring framework bietet die folgenden Funktionen -
Richtet die Dinge so ein, dass eine http-Anfrage als reguläre Clojure-HashMap in Ihre Webanwendung eingeht, und macht sie ebenfalls so, dass Sie eine Antwort als HashMap zurückgeben können.
Bietet eine Spezifikation, die genau beschreibt, wie diese Anforderungs- und Antwortkarten aussehen sollten.
Bringt einen Webserver (Jetty) mit und verbindet Ihre Webanwendung damit.
Das Ring-Framework kann automatisch einen Webserver starten und stellt sicher, dass die Clojure-Anwendung auf diesem Server funktioniert. Dann kann man auch das Compojure-Framework verwenden. Auf diese Weise können Routen erstellt werden, auf die jetzt die meisten modernen Webanwendungen entwickelt werden.
Creating your first Clojure application - Das folgende Beispiel zeigt, wie Sie Ihre erste Webanwendung in Clojure erstellen können.
(ns my-webapp.handler
(:require [compojure.core :refer :all]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
(GET "/" [] "Hello World")
(route/not-found "Not Found"))
(def app
(wrap-defaults app-routes site-defaults))
Schauen wir uns die folgenden Aspekte des Programms an:
Das ‘defroutes’ wird zum Erstellen von Routen verwendet, sodass Anforderungen an die Webanwendung an verschiedene Routen an verschiedene Funktionen in Ihrer Clojure-Anwendung gerichtet werden können.
Im obigen Beispiel wird das "/" als Standardroute bezeichnet. Wenn Sie also zur Basis Ihrer Webanwendung navigieren, wird die Zeichenfolge "Hello World" an den Webbrowser gesendet.
Wenn der Benutzer eine URL trifft, die von der Clojure-Anwendung nicht verarbeitet werden kann, wird die Zeichenfolge "Nicht gefunden" angezeigt.
Wenn Sie die Clojure-Anwendung ausführen, wird Ihre Anwendung standardmäßig als localhost geladen: 3000. Wenn Sie also zu diesem Speicherort navigieren, erhalten Sie die folgende Ausgabe.
Webanwendungen - Hinzufügen weiterer Routen zu Ihrer Webanwendung
Sie können Ihrer Webanwendung auch weitere Routen hinzufügen. Das folgende Beispiel zeigt, wie dies erreicht wird.
(ns my-webapp.handler
(:require [compojure.core :refer :all]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
(GET "/" [] "Hello World")
(GET "/Tutorial" [] "This is a tutorial on Clojure")
(route/not-found "Not Found"))
(def app
(wrap-defaults app-routes site-defaults))
Sie können sehen, dass das Hinzufügen einer Route in der Anwendung so einfach ist wie das Hinzufügen einer weiteren GET-Funktion mit der URL-Route. (GET "/ Tutorial" [] "Dies ist ein Tutorial zu Clojure")
Wenn Sie zum Speicherort navigieren http://localhost:3000/Tutorialerhalten Sie die folgende Ausgabe.
In diesem Kapitel werden die von Clojure bereitgestellten automatisierten Testoptionen erläutert.
Testen auf Clientanwendungen
Um Tests für das Clojure-Framework verwenden zu können, müssen Sie die Abhängigkeiten unter verwenden https://github.com/slagyr/speclj#manual-installation
Diese URL enthält die specljFramework, das als testdatengesteuertes oder verhaltensgesteuertes Testframework für Clojure verwendet wird. Sie müssen sicherstellen, dass Sie das Clojure 1.7.0-Framework verwenden, wenn Sie eine der 'speclj'-Bibliotheken verwenden. Standardmäßig unterscheiden sich die Testdateien von den Clojure-Codedateien und müssen in einem 'spec'-Verzeichnis abgelegt werden.
Es folgt ein Beispielcode für eine Testdatei.
(ns change.core-spec
(:require [speclj.core :refer :all]))
(describe "Truth"
(it "is true"
(should true))
(it "is not false"
(should-not false)))
(run-specs)
Folgende Dinge müssen über den obigen Code beachtet werden:
Wir müssen zuerst sicherstellen, dass die Anweisung 'require' verwendet wird, um alle Kernbibliotheken in das Framework 'speclj' aufzunehmen.
Als nächstes folgt die Funktion 'Beschreiben'. Dies wird verwendet, um eine Beschreibung für den zu erstellenden Testfall bereitzustellen.
Die nächste Funktion ist die 'it'-Funktion, die der eigentliche Testfall ist. Im ersten Testfall ist die Zeichenfolge "is true" der Name des Testfalls.
Sollte und sollte-nicht bekannt sind als assertions. Alle Aussagen beginnen mit sollte. Sollte und sollte-nicht sind nur zwei der vielen verfügbaren Behauptungen. Beide nehmen Ausdrücke, die sie auf Wahrhaftigkeit bzw. Falschheit prüfen.
Wenn Sie den Testfall ausführen, erhalten Sie die folgende Ausgabe. Die Ausgabe zeigt die Zeit in Millisekunden an, die der Testfall benötigt.
←[32m.←[0m←[32m.←[0m
Finished in 0.00014 seconds
Testen für webbasierte Anwendungen
Seleniumist eines der wichtigsten Frameworks zum Testen moderner webbasierter Anwendungen. Es sind auch Clojure-Bibliotheken verfügbar, mit denen webbasierte Anwendungen getestet werden können.
Schauen wir uns an, wie wir die Selenium-Bibliotheken zum Testen von webbasierten Clojure-Anwendungen verwenden können.
Step 1- Der erste Schritt besteht darin, sicherzustellen, dass wir das Ring and Compojure-Framework verwenden, um eine webbasierte Anwendung zu erstellen, die getestet werden muss. Verwenden wir eines der Beispiele aus unseren früheren Kapiteln. Der folgende Code ist eine einfache Webanwendung, die im Browser „Hello World“ anzeigt.
(ns my-webapp.handler
(:require [compojure.core :refer :all]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
(GET "/" [] "Hello World")
(route/not-found "Not Found"))
(def app
(wrap-defaults app-routes site-defaults))
Step 2 - Stellen Sie als Nächstes sicher, dass Sie die Selenium-JAR-Datei herunterladen https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-server/2.47.0 und füge es in deinen Klassenpfad ein.
Step 3 - Stellen Sie außerdem sicher, dass Sie den Web-Treiber 'clj' herunterladen, der zum Ausführen des Webtests vom folgenden Speicherort verwendet wird.
https://clojars.org/clj-webdriver/versions/0.7.1
Step 4 - Erstellen Sie in Ihrem Projektverzeichnis ein anderes Verzeichnis mit dem Namen "Features" und eine Datei mit dem Namen "config.clj".
Step 5 - Fügen Sie als Nächstes den folgenden Code zur im vorherigen Schritt erstellten Datei 'config.clj' hinzu.
ns clj-webdriver-tutorial.features.config)
(def test-port 3000)
(def test-host "localhost")
(def test-base-url (str "http://" test-host ":" test-port "/"))
Der obige Code weist das Webtest-Framework grundsätzlich an, die Anwendung zu testen, die unter der URL geladen wird http://localhost:3000
Step 6 - Zum Schluss schreiben wir unseren Code, um unseren Test durchzuführen.
(ns clj-webdriver-tutorial.features.homepage
(:require [clojure.test :refer :all]
[ring.adapter.jetty :refer [run-jetty]]
[clj-webdriver.taxi :refer :all]
[clj-webdriver-tutorial.features.config :refer :all]
[clj-webdriver-tutorial.handler :refer [app-routes]]))
(ns clj-webdriver-tutorial.features.homepage
(:require [clojure.test :refer :all]
[ring.adapter.jetty :refer [run-jetty]]
[clj-webdriver.taxi :refer :all]
[clj-webdriver-tutorial.features.config :refer :all]
[clj-webdriver-tutorial.handler :refer [app-routes]]))
(defn start-server []
(loop [server (run-jetty app-routes {:port test-port, :join? false})]
(if (.isStarted server)
server
(recur server))))
(defn stop-server [server]
(.stop server))
(defn start-browser []
(set-driver! {:browser :firefox}))
(defn stop-browser []
(quit))
(deftest homepage-greeting
(let [server (start-server)]
(start-browser)
(to test-base-url)
(is (= (text "body") "Hello World"))
(stop-browser)
(stop-server server)))
Der obige Code führt die folgenden Aktionen aus:
- Starten Sie den Server für die Anwendung.
- Öffnen Sie den Stammpfad im Browser.
- Überprüfen Sie, ob die Meldung "Hallo Welt" auf der Seite vorhanden ist.
- Schließen Sie den Browser.
- Fahren Sie den Server herunter.
Eine Sache, die die Clojure-Bibliothek so leistungsfähig macht, ist die Anzahl der für das Clojure-Framework verfügbaren Bibliotheken. Wir haben bereits so viele Bibliotheken gesehen, die in unseren früheren Beispielen für Webtests, Webentwicklung, Entwicklung von Swing-basierten Anwendungen und die JDBC-Bibliothek für die Verbindung mit MySQL-Datenbanken verwendet wurden. Es folgen nur einige Beispiele für einige weitere Bibliotheken.
data.xml
Diese Bibliothek ermöglicht es Clojure, mit XML-Daten zu arbeiten. Die zu verwendende Bibliotheksversion lautet org.clojure / data.xml "0.0.8". Die Datei data.xml unterstützt das Parsen und Ausgeben von XML. Die Parsing-Funktionen lesen XML aus einem Reader oder InputStream.
Beispiel
Es folgt ein Beispiel für die Datenverarbeitung von einer Zeichenfolge zu XML.
(ns clojure.examples.example
(use 'clojure.data.xml)
(:gen-class))
(defn Example []
(let [input-xml (java.io.StringReader. "<?xml version = \"1.0\"
encoding = \"UTF-8\"?><example><clo><Tutorial>The Tutorial
value</Tutorial></clo></example>")]
(parse input-xml)))
#clojure.data.xml.Element{
:tag :example, :attrs {}, :content (#clojure.data.xml.Element {
:tag :clo, :attrs {}, :content (#clojure.data.xml.Element {
:tag :Tutorial, :attrs {},:content ("The Tutorial value")})})}
(Example)
data.json
Diese Bibliothek ermöglicht es Clojure, mit JSON-Daten zu arbeiten. Die zu verwendende Bibliotheksversion ist org.clojure / data.json "0.2.6".
Beispiel
Im Folgenden finden Sie ein Beispiel für die Verwendung dieser Bibliothek.
(ns clojure.examples.example
(:require [clojure.data.json :as json])
(:gen-class))
(defn Example []
(println (json/write-str {:a 1 :b 2})))
(Example)
Ausgabe
Das obige Programm erzeugt die folgende Ausgabe.
{\"a\":1,\"b\":2}
data.csv
Mit dieser Bibliothek kann Clojure arbeiten ‘csv’Daten. Die zu verwendende Bibliotheksversion ist org.clojure / data.csv "0.1.3".
Beispiel
Im Folgenden finden Sie ein Beispiel für die Verwendung dieser Bibliothek.
(ns clojure.examples.example
(require '[clojure.data.csv :as csv]
'[clojure.java.io :as io])
(:gen-class))
(defn Example []
(with-open [in-file (io/reader "in-file.csv")]
(doall
(csv/read-csv in-file)))
(with-open [out-file (io/writer "out-file.csv")]
(csv/write-csv out-file
[[":A" "a"]
[":B" "b"]])))
(Example)
Im obigen Code liest die Funktion 'csv' zuerst eine aufgerufene Datei in-file.csvund legen Sie alle Daten in der Variablen in der Datei. Als nächstes verwenden wir die Funktion write-csv, um alle Daten in eine aufgerufene Datei zu schreibenout-file.csv.