Introduction à Clojure et ses fonctionnalités
Introduction à Clojure et ses fonctionnalités
#clojure
Table des matières
À propos 1
Remarques 2
Versions 3
Examples 3
Installation et configuration 3
Option 1: Leiningen 3
Linux 3
OS X 4
les fenêtres 4
Option 3: démarrage 4
Examples 7
Chapitre 3: Atome 8
Introduction 8
Examples 8
Définir un atome 8
Chapitre 4: clj-time 10
Introduction 10
Examples 10
Créer un temps Joda 10
Chapitre 5: [Link] 13
Introduction 13
Examples 13
Chapitre 6: [Link] 15
Syntaxe 15
Remarques 15
Examples 15
Fiche technique 17
Spécifications de la carte 17
Collections 18
Séquences 20
Chapitre 7: [Link] 21
Examples 21
est 21
sont 22
Enveloppez chaque test ou tous les tests avec des accessoires d'utilisation 22
Exécution de tests avec Leiningen 23
Syntaxe 24
Examples 24
Collections 24
Des listes 24
Séquences 27
Vecteurs 31
Ensembles 35
Plans 37
Examples 43
Table lumineuse 43
Emacs 44
Atome 44
Spacemacs + CIDER 45
Vim 46
Examples 47
Canaux de fermeture 49
Remarques 51
Examples 51
Littéraux correspondants 51
Faire correspondre un vecteur 51
Examples 53
Serveurs Web 54
bases de données 54
divers 54
Examples 56
Vue d'ensemble 58
Conseils: 59
Introduction 61
Remarques 61
Examples 61
Exemples mathématiques 61
Introduction 62
Examples 62
Évaluation de la fonction 62
Jolie impression 62
Syntaxe 64
Remarques 64
Examples 64
Examples 66
Paramètres et Arity 66
Arity 67
Syntaxe 70
Remarques 70
Examples 70
Introduction 73
Examples 73
Fil Dernier (- >>) 73
Thread as (as->) 73
Examples 75
Vue d'ensemble 75
Remarques: 75
Introduction 76
Remarques 76
Examples 76
Application de transducteurs 77
Syntaxe 79
Remarques 79
Examples 79
Types de variables 79
Examples 80
Vérité 80
Booléens 80
Crédits 81
À propos
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: clojure
It is an unofficial and free clojure ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official clojure.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to info@[Link]
[Link] 1
Chapitre 1: Commencer avec clojure
Remarques
Ses fonctionnalités prennent en charge le style fonctionnel de programmation avec des fonctions
de première classe et des valeurs immuables par défaut. L'utilisation de variables réaffectables
n'est pas aussi facile dans Clojure que dans de nombreux langages traditionnels, car les variables
doivent être créées et mises à jour comme des objets conteneurs. Cela encourage l'utilisation de
valeurs pures qui resteront telles qu'elles étaient au moment où elles ont été vues pour la dernière
fois. Cela rend généralement le code beaucoup plus prévisible, testable et compatible avec la
concurrence. Cela fonctionne également pour les collections, car les structures de données
intégrées de Clojure sont persistantes.
Pour des performances optimales, Clojure prend en charge les indices de type pour éliminer les
réflexions inutiles lorsque cela est possible. En outre, des groupes de modifications de collections
persistantes peuvent être apportées à des versions transitoires , ce qui réduit la quantité d'objets
impliqués. Cela n'est pas nécessaire la plupart du temps, car les collections persistantes sont
rapides à copier car elles partagent la plupart de leurs données. Leurs garanties de performance
ne sont pas loin de leurs homologues mutables.
En raison de sa syntaxe simple et de son extensibilité élevée (via des macros, l'implémentation
d'interfaces de base et la réflexion), certaines fonctionnalités de langage couramment rencontrées
peuvent être ajoutées à Clojure avec des bibliothèques. Par exemple, [Link] apporte un
vérificateur de type statique, [Link] apporte des mécanismes de concurrence simples basés
sur les [Link] , [Link] apporte la programmation logique.
Conçu comme un langage hébergé, il peut interagir avec la plate-forme sur laquelle il s'exécute.
Bien que la cible principale soit JVM et l'écosystème entier derrière Java, d'autres
implémentations peuvent également s'exécuter dans d'autres environnements, tels que
ClojureCLR s'exécutant sur Common Language Runtime ou ClojureScript s'exécutant sur des
[Link] 2
environnements d'exécution JavaScript (y compris les navigateurs Web). Bien que certaines
implémentations puissent ne pas avoir certaines fonctionnalités de la version JVM, elles sont
toujours considérées comme une famille de langues.
Versions
1.2.1 2011-03-25
1.2 2010-08-19
1.1 2010-01-04
1.0 2009-05-04
Examples
Installation et configuration
Option 1: Leiningen
Nécessite JDK 6 ou plus récent.
Le moyen le plus simple de commencer avec Clojure est de télécharger et d'installer Leiningen,
l'outil standard de facto pour gérer les projets Clojure, puis d'exécuter lein repl pour ouvrir une
REPL .
Linux
[Link] 3
OS X
Suivez les étapes ci-dessus pour Linux ou installez-les avec les gestionnaires de paquets macOS.
lein self-install
les fenêtres
Les versions de Clojure sont publiées sous forme de simples fichiers JAR à exécuter sur la JVM.
C'est ce qui se passe généralement dans les outils de construction Clojure.
Vous devrez peut-être remplacer le [Link] dans cette commande par le nom du
fichier JAR que vous avez réellement téléchargé.
Pour une meilleure expérience REPL en ligne de commande (par exemple, passer en rlwrap
vos commandes précédentes), vous pouvez installer rlwrap : rlwrap java -cp clojure-
[Link] [Link]
Option 3: démarrage
Nécessite JDK 7 ou plus récent.
[Link] 4
Boot est un outil de construction Clojure polyvalent. Comprendre cela nécessite une certaine
connaissance de Clojure, donc ce n'est peut-être pas la meilleure option pour les débutants.
Consultez le site Web (cliquez sur Démarrer ) pour obtenir des instructions d'installation.
Une fois installé et dans votre PATH , vous pouvez exécuter boot repl n'importe où pour démarrer
une REPL Clojure.
Vous devriez être en mesure de lancer une REPL Clojure maintenant. Si vous ne savez pas
comment, suivez la section Installation et configuration de cette rubrique. Une fois que vous
l'avez lancé, tapez ce qui suit:
Puis appuyez sur Entrée . Cela devrait imprimer Hello, world! , suivi de la valeur de retour de cette
expression, nil .
Si vous souhaitez lancer des actions instantanément, essayez REPL en ligne. Par exemple,
[Link] .
Après avoir suivi les instructions ci-dessus et installé Leiningen, démarrez un nouveau projet en
exécutant:
Cela va configurer un projet Clojure avec le modèle Leiningen par défaut dans le dossier <project-
name> . Il existe plusieurs modèles pour Leiningen, qui affectent la structure du projet. Le plus
commun est le modèle "app" utilisé, qui ajoute une fonction principale et prépare le projet à être
compressé dans un fichier jar (dont la fonction principale est le point d'entrée de l'application).
Cela peut être réalisé en exécutant:
En supposant que vous avez utilisé le modèle d'application pour créer une nouvelle application,
vous pouvez tester que tout a été correctement configuré, en entrant le répertoire créé et en
exécutant l'application en utilisant:
lein run
[Link] 5
Si vous voyez Hello, World! sur votre console, vous êtes prêt et prêt à créer votre application.
Vous pouvez emballer cette application simple dans deux fichiers jar avec la commande suivante:
lein uberjar
Remarque: vous devez installer Boot avant d'essayer cet exemple. Voir la section Installation et
configuration si vous ne l'avez pas encore installée.
Le démarrage permet de créer des fichiers Clojure exécutables en utilisant la ligne shebang (#!).
Placez le texte suivant dans un fichier de votre choix (cet exemple suppose qu'il se trouve dans le
"répertoire de travail actuel" et qu'il s'appelle [Link] ).
#!/usr/bin/env boot
Puis marquez-le comme exécutable (le cas échéant, généralement en exécutant chmod +x
[Link] ).
... et lancez-le ( ./[Link] ).
Pour exécuter l'application: boot run . Les autres commandes sont spécifiées dans [Link] et
décrites dans le fichier README.
[Link] 6
Chapitre 2: Analyse des journaux avec
clojure
Examples
Analyser une ligne de journal avec record et regex
Essaye-le :
(parser sample)
Résultat :
[Link] 7
Chapitre 3: Atome
Introduction
Un atome dans Clojure est une variable qui peut être modifiée tout au long de votre programme
(espace de noms). Comme la plupart des types de données dans Clojure sont immuables (ou non
modifiables) - vous ne pouvez pas modifier la valeur d'un nombre sans le redéfinir - les atomes
sont essentiels dans la programmation de Clojure.
Examples
Définir un atome
Pour définir un atome, utilisez un def ordinaire, mais ajoutez une fonction atom avant, comme ceci:
Cela crée un atom de valeur 0 . Les atomes peuvent être de tout type:
Pour lire la valeur d'un atome, il suffit de mettre le nom de l'atome avec un @ avant:
@counter ; => 0
Il y a deux commandes pour changer un atome, swap! et reset! . swap! est donné des commandes
et modifie l'atome en fonction de son état actuel. reset! change complètement la valeur de
l'atome, quelle que soit la valeur de l'atome d'origine:
[Link] 8
(def count (atom 0))
[Link] 9
Chapitre 4: clj-time
Introduction
Ce document traite de la manière de manipuler la date et l’heure en clair.
Pour l'utiliser dans votre application, allez dans votre fichier [Link] et incluez [clj-time
"<numéro_version>"] dans votre section: dependencies.
Examples
Créer un temps Joda
[Link] 10
Vérifier si une heure est comprise dans un intervalle de temps
Cette fonction indique si une heure donnée se situe dans un intervalle de temps donné.
La fonction d'intervalle utilisée est exclusive , ce qui signifie qu'elle n'inclut pas le second
argument de la fonction dans l'intervalle. Par exemple:
La bibliothèque [Link] peut aider à convertir d'autres formats de date et heure au format
d'heure joda ([Link] / date-time). Les autres formats incluent le format long Java , la chaîne
, la date , la date SQL .
Pour convertir l'heure à partir d'autres formats d'heure, incluez la bibliothèque et utilisez la fonction
from-, par exemple
cljs-time nous donne l'option d'ajouter / soustraire des dates-heures à d'autres dates-heures. La
date à laquelle les temps ajoutés doivent être sous forme de jours, mois, années, heures, etc.
;; Addition
(t/plus example-date (t/months 1)) ;; #<DateTime 2016-02-01T00:00:00.000Z>
(t/plus example-date (t/years 1)) ;; #<DateTime 2017-01-01T00:00:00.000Z>
[Link] 11
;; Subtraction
(t/minus example-date (t/days 1)) ;; #<DateTime 2015-12-31T00:00:00.000Z>
(t/minus example-date (t/hours 12)) ;; #<DateTime 2015-12-31T12:00:00.000Z>
[Link] 12
Chapitre 5: [Link]
Introduction
Ce document donne diverses fonctionnalités de base offertes par clojure. Il n'y a pas de
dépendance explicite nécessaire pour cela et cela fait partie de [Link].
Examples
Définir des fonctions en clojure
(defn x [a b]
(* a b)) ;; public function
=> (x 3 2) ;; 6
=> (x 0 9) ;; 0
(defn- y [a b]
(+ a b)) ;; private function
=> (x (y 1 2) (y 2 3)) ;; 15
Appliquée sur une carte, retourne une nouvelle carte avec des paires de valeurs de clés nouvelles
ou mises à jour.
Il peut être utilisé pour ajouter de nouvelles informations dans une carte existante.
Il peut également être utilisé sur un vecteur pour remplacer la valeur à l'index spécifié.
(assoc [3 5 6 7] 2 10) ;; [3 5 10 7]
(assoc [1 2 3 4] 6 6) ;; [Link]
Les comparaisons sont des fonctions dans la vie. Ce que cela signifie en (2>1) est (> 2 1) en clair.
Voici tous les opérateurs de comparaison en cloche.
[Link] 13
1. Plus grand que
(> 2 1) ;; true
(> 1 2) ;; false
2. Moins que
(< 2 1) ;; false
(>= 2 1) ;; true
(>= 2 2) ;; true
(>= 1 2) ;; false
4. Inférieur ou égal à
(<= 2 1) ;; false
(<= 2 2) ;; true
(<= 1 2) ;; true
5. Égal à
(= 2 2) ;; true
(= 2 10) ;; false
6. Pas égal à
(not= 2 2) ;; false
(not= 2 10) ;; true
Cela retourne une carte sans les paires clé-valeur pour les clés mentionnées dans l'argument de
la fonction. Il peut être utilisé pour supprimer des informations de la carte existante.
[Link] 14
Chapitre 6: [Link]
Syntaxe
• :: est un raccourci un mot-clé qualifié par un espace de noms. Par exemple, si nous sommes
dans l'espace de noms user: :: foo est un raccourci pour: user / foo
• #: ou # - syntaxe littérale de la carte pour qualifier les clés d'une carte par un espace de
noms
Remarques
Clojure spec est une nouvelle bibliothèque de spécifications / contrats pour clojure disponible à
partir de la version 1.9.
Les spécifications sont exploitées de diverses manières, notamment en étant incluses dans la
documentation, la validation des données, la génération de données pour les tests et bien plus
encore.
Examples
Utiliser un prédicat comme spécification
Toute fonction de prédicat peut être utilisée en tant que spécification. Voici un exemple simple:
([Link]/valid? odd? 1)
;;=> true
([Link]/valid? odd? 2)
;;=> false
le valid? function prendra une spec et une valeur et retournera true si la valeur est conforme à la
spécification et false sinon.
Nous pouvons écrire une spécification pour cette fonction en définissant une spécification de
[Link] 15
fonction du même nom:
([Link]/fdef nat-num-count
:args (s/cat :nums (s/coll-of number?))
:ret integer?
:fn #(<= (:ret %) (-> % :args :nums count)))
:args prend une spécification de regex qui décrit la séquence des arguments par une étiquette de
mot-clé correspondant au nom de l'argument et à une spécification correspondante. La raison
pour laquelle la spécification requise par :args est une spécification de regex est de prendre en
charge plusieurs arités pour une fonction. :ret spécifie une spécification pour la valeur de retour
de la fonction.
:fnest une spécification qui contraint la relation entre les :args et :ret . Il est utilisé comme
propriété lorsqu'il est exécuté via [Link]. Il est appelé avec un seul argument: une carte avec
deux clés:: :args (les arguments conformes à la fonction) et :ret (la valeur de retour de la
fonction).
En plus des prédicats fonctionnant en tant que spécifications, vous pouvez enregistrer une
spécification globalement en utilisant [Link]/def . def exige qu'une spécification enregistrée
soit nommée par un mot clé qualifié par un espace de nommage:
([Link]/valid? ::odd-nums 1)
;;=> true
([Link]/valid? ::odd-nums 2)
;;=> false
Une fois enregistrée, une spécification peut être référencée globalement n'importe où dans un
programme Clojure.
La syntaxe ::odd-nums est un raccourci pour :user/odd-nums , en supposant que nous sommes dans
l'espace de noms de l' user . :: qualifiera le symbole qu'il précède avec le nom actuel.
Plutôt que de passer le prédicat, nous pouvons passer le nom de la spécification à valid? , et cela
fonctionnera de la même manière.
[Link]/and& [Link]/or peuvent être utilisés pour créer des spécifications plus
complexes, en utilisant plusieurs spécifications ou prédicats:
([Link]/valid? ::pos-odd 1)
;;=> true
[Link] 16
([Link]/valid? ::pos-odd -3)
;;=> false
orfonctionne de manière similaire, avec une différence significative. Lors de la définition d'une or
une spécification, vous devez marquer chaque branche possible avec un mot-clé. Ceci est utilisé
pour fournir des branches spécifiques qui échouent dans les messages d'erreur:
([Link]/valid? ::big-or-small 1)
;;=> true
([Link]/conform ::big-or-small 5)
;; => [:small 5]
Fiche technique
À un moment donné, une syntaxe de lecteur ou une prise en charge intégrée pour la qualification
des clés d'enregistrement par l'espace de nom des enregistrements peut être introduite. Ce
support existe déjà pour les cartes.
Spécifications de la carte
Vous pouvez spécifier une carte en spécifiant les clés qui doivent être présentes sur la carte:
[Link] 17
([Link]/def ::age pos-int?)
([Link]/def ::occupation string?)
:reqest un vecteur de clés devant être présent dans la carte. Vous pouvez spécifier des options
supplémentaires telles que :opt , un vecteur de clés facultatif.
Les exemples jusqu'à présent exigent que les clés du nom soient qualifiées par des espaces de
noms. Mais il est courant que les clés de carte ne soient pas qualifiées. Pour ce cas, [Link]
fournit: req et: opt équivalents pour les clés non qualifiées :req-un et :opt-un . Voici le même
exemple, avec des clés non qualifiées:
Notez que les spécifications fournies dans le vecteur :req-un sont toujours qualifiées. [Link],
confirmera automatiquement les versions non qualifiées dans la carte lors de la conformité des
valeurs.
La syntaxe littérale de la carte d'espace de noms vous permet de qualifier toutes les clés d'une
carte par un seul espace de noms succinct. Par exemple:
Notez la syntaxe spéciale #: reader. Nous suivons cela avec l'espace de noms que nous
souhaitons qualifier par toutes les clés de la carte. Celles-ci seront ensuite vérifiées par rapport
aux spécifications correspondant à l'espace de noms fourni.
Collections
Vous pouvez spécifier des collections de différentes manières. coll-of vous permet de spécifier
des collections et de fournir des contraintes supplémentaires. Voici un exemple simple:
[Link] 18
([Link]/valid? ([Link]/coll-of int?) '(1 2 3))
;; => true
Les options de contrainte suivent les spécifications / prédicats principaux de la collection. Vous
pouvez contraindre le type de collection avec :kind comme ceci:
Ce qui précède est faux car la collection transmise n'est pas un vecteur.
Ce qui précède est faux car tous les éléments de l'ensemble ne sont pas ints.
Vous pouvez également imposer l'unicité des éléments de la collection avec :distinct :
coll-of s'assure que tous les éléments d'une séquence sont vérifiés. Pour les grandes collections,
cela peut être très inefficace. every se comporte exactement comme coll-of , sauf qu'il
échantillonne seulement un nombre relativement petit d'éléments de la séquence pour la
conformité. Cela fonctionne bien pour les grandes collections. Voici un exemple:
[Link] 19
([Link]/valid? ([Link]/every int? :distinct true) [1 2 3 4 5])
;; => true
map-of est similaire à coll-of , mais pour les cartes. Comme les cartes ont à la fois des clés et des
valeurs, vous devez fournir une spécification pour la clé et une spécification pour la valeur:
Comme coll-of , la conformité de toutes les clés / valeurs coll-of map-of contrôles. Pour les
grandes cartes, cela sera inefficace. A l'instar de coll-of , une map-of fournitures à every-kv pour
échantillonner efficacement un nombre relativement petit de valeurs à partir d'une grande carte:
Séquences
spec peut décrire et être utilisé avec des séquences arbitraires. Il prend en charge cela via un
certain nombre d'opérations de spécification regex.
catnécessite des étiquettes pour chaque spécification utilisée pour décrire la séquence. cat décrit
une séquence d'éléments et une spécification pour chacun.
altest utilisé pour choisir parmi un certain nombre de spécifications possibles pour un élément
donné dans une séquence. Par exemple:
alt exige également que chaque spécification soit étiquetée par un mot-clé.
Les séquences de regex peuvent être composées de manières très intéressantes et puissantes
pour créer des spécifications de description de séquence arbitrairement complexes. Voici un
exemple légèrement plus complexe:
Ici ::complex-seq validera une séquence d'une ou plusieurs paires d'éléments, la première étant un
int et la seconde étant une carte de mot-clé à int.
[Link] 20
Chapitre 7: [Link]
Examples
est
Vous pouvez regrouper des assertions associées dans des deftest unitaires de test dans un
contexte à l'aide de la macro testing :
(deftest add-nums
(testing "Positive cases"
(is (= 2 (+ 1 1)))
(is (= 4 (+ 2 2))))
(testing "Negative cases"
(is (= -1 (+ 2 -3)))
(is (= -4 (+ 8 -12)))))
Cela aidera à clarifier la sortie du test lors de l'exécution. Notez que les testing doivent avoir lieu à
l'intérieur d'un deftest .
deftestest une macro pour définir un test unitaire, similaire aux tests unitaires dans d'autres
langues.
(deftest add-nums
(is (= 2 (+ 1 1)))
(is (= 3 (+ 1 2))))
[Link] 21
Nous définissons ici un test appelé add-nums , qui teste la fonction + . Le test a deux assertions.
Vous pouvez ensuite exécuter le test comme ceci dans votre espace de noms actuel:
(run-tests)
Ou vous pouvez simplement exécuter les tests pour l'espace de noms dans lequel se trouve le
test:
(run-tests 'your-ns)
sont
Le are macro fait également partie de la [Link] bibliothèque. Il vous permet de faire
plusieurs assertions sur un modèle.
Par exemple:
(are [x y] (= x y)
4 (+ 2 2)
8 (* 2 4))
=> true
Ici, (= xy) agit comme un modèle qui prend chaque argument et crée une is l' affirmation hors de
celui - ci.
(do
(is (= 4 (+ 2 2)))
(is (= 8 (* 2 4))))
Enveloppez chaque test ou tous les tests avec des accessoires d'utilisation
use-fixturespermet d'emballer chaque deftest dans l'espace de nommage avec le code qui
s'exécute avant et après le test. Il peut être utilisé pour des luminaires ou des bouts.
Les appareils ne sont que des fonctions qui prennent en charge la fonction de test et l’exécutent
avec d’autres étapes nécessaires (avant / après, emballage).
(ns [Link]
(require [[Link] :refer :all])
[Link] 22
Utilisé avec :once , il enveloppe une série complète de tests dans l'espace de noms actuel avec la
fonction
Si vous utilisez Leiningen et que vos tests se trouvent dans le répertoire de test de la racine de
votre projet, vous pouvez exécuter vos tests en utilisant le lein test
[Link] 23
Chapitre 8: Collections et séquences
Syntaxe
• '() → ()
• '(1 2 3 4 5) → (1 2 3 4 5)
• '(1 foo 2 bar 3) → (1 'foo 2 'bar 3)
• ( list 1 2 3 4 5) → (1 2 3 4 5)
• ( list* [1 2 3 4 5]) → (1 2 3 4 5)
• [] → []
• [1 2 3 4 5] → [1 2 3 4 5]
• ( vector 1 2 3 4 5) → [1 2 3 4 5]
• ( vec '(1 2 3 4 5)) → [1 2 3 4 5]
• {} => {}
• {:keyA 1 :keyB 2} → {:keyA 1 :keyB 2}
• {:keyA 1, :keyB 2} → {:keyA 1 :keyB 2}
• ( hash-map :keyA 1 :keyB 2) → {:keyA 1 :keyB 2}
• ( sorted-map 5 "five" 1 "one") → {1 "one" 5 "five"} (les entrées sont triées par clé
lorsqu'elles sont utilisées comme une séquence)
• #{} → #{}
• #{1 2 3 4 5} → #{4 3 2 5 1} (non ordonné)
• ( hash-set 1 2 3 4 5) → #{2 5 4 1 3} (non ordonné)
• ( sorted-set 2 5 4 3 1) → #{1 2 3 4 5}
Examples
Collections
Toutes les collections Clojure intégrées sont immuables et hétérogènes, ont une syntaxe littérale
et prennent en charge les fonctions conj , count et seq .
• renvoie une nouvelle collection équivalente à une collection existante avec un élément
conj
"ajouté", soit dans le temps "constant" ou logarithmique. Ce que cela signifie exactement
dépend de la collection.
• count renvoie le nombre d'éléments d'une collection, en temps constant.
• seq renvoie nil pour une collection vide ou une séquence d'éléments pour une collection non
vide, à temps constant.
Des listes
()
[Link] 24
;;=> ()
Une liste de Clojure est une liste à liens simples . conj "joint" un nouvel élément à la collection
dans l'emplacement le plus efficace. Pour les listes, c'est au début:
(conj () :foo)
;;=> (:foo)
Contrairement aux autres collections, les listes non vides sont évaluées comme des appels à des
formulaires, macros ou fonctions spéciaux lorsqu'elles sont évaluées. Par conséquent, tant que
(:foo) est la représentation littérale de la liste contenant :foo comme seul élément, l'évaluation de
(:foo) dans une REPL provoquera une IllegalArgumentException car un mot clé ne peut pas être
appelé comme fonction nullary .
(:foo)
;; [Link]: Wrong number of args passed to keyword: :foo
Pour empêcher Clojure d’évaluer une liste non vide, vous pouvez la quote :
'(:foo)
;;=> (:foo)
'(:foo :bar)
;;=> (:foo :bar)
(+ 1 1)
;;=> 2
'(1 (+ 1 1) 3)
;;=> (1 (+ 1 1) 3)
Pour cette raison, vous voudrez généralement utiliser list , une fonction variadic qui évalue tous
ses arguments et utilise ces résultats pour construire une liste:
(list)
;;=> ()
(list :foo)
;;=> (:foo)
(list 1 (+ 1 1) 3)
;;=> (1 2 3)
[Link] 25
(count ())
;;=> 0
Vous pouvez tester si quelque chose est une liste en utilisant la list? prédicat:
(list? ())
;;=> true
(list? nil)
;;=> false
(list? 42)
;;=> false
(list? :foo)
;;=> false
(peek ())
;;=> nil
(peek '(:foo))
;;=> :foo
Vous pouvez obtenir une nouvelle liste sans le premier élément en utilisant pop :
(pop '(:foo))
;;=> ()
Notez que si vous essayez de faire pop une liste vide, vous obtiendrez une IllegalStateException :
(pop ())
;; [Link]: Can't pop empty list
Enfin, toutes les listes sont des séquences, vous pouvez donc tout faire avec une liste que vous
pouvez faire avec toute autre séquence. En effet, à l'exception de la liste vide, l'appel de seq sur
une liste renvoie exactement le même objet:
[Link] 26
(seq ())
;;=> nil
(seq '(:foo))
;;=> (:foo)
Séquences
Une séquence ressemble beaucoup à une liste: c'est un objet immuable qui peut vous donner son
first élément ou le rest de ses éléments en temps constant. Vous pouvez également cons truct
une nouvelle séquence d'une séquence existante et un élément de coller au début.
Vous pouvez tester si quelque chose est une séquence en utilisant le seq? prédicat:
(seq? nil)
;;=> false
(seq? 42)
;;=> false
(seq? :foo)
;;=> false
(seq? ())
;;=> true
Tout ce que vous obtenez en appelant seq ou rseq ou des keys ou des vals sur une collection non
vide est également une séquence:
[Link] 27
(seq? (rseq [:foo :bar]))
;;=> true
Rappelez-vous que toutes les listes sont des séquences, mais toutes les séquences ne sont pas
des listes. Alors que les listes prennent en charge les fonctions de peek et de pop et count en temps
constant, en général, une séquence n'a pas besoin de prendre en charge l'une de ces fonctions.
Si vous essayez d'appeler peek ou pop sur une séquence qui ne prend pas également en charge
l'interface de pile de Clojure, vous obtiendrez une ClassCastException :
[Link] 28
Si vous appelez count sur une séquence qui n'implémente pas le count en temps constant, vous
n'obtiendrez pas d'erreur. Clojure traversera toute la séquence jusqu'à la fin, puis retournera le
nombre d'éléments qu'il a parcourus. Cela signifie que, pour les séquences générales, le count est
linéaire, pas constant, le temps. Vous pouvez tester si quelque chose prend en charge le count
temps constant en utilisant le counted? prédicat:
Comme mentionné ci-dessus, vous pouvez utiliser d' first pour obtenir le premier élément d'une
séquence. Notez que le first appelera seq sur leur argument, donc il peut être utilisé sur tout
"seqable", pas seulement sur les séquences réelles:
(first nil)
;;=> nil
(first '(:foo))
;;=> :foo
(first [:foo])
;;=> :foo
(first #{:foo})
;;=> :foo
Comme mentionné ci-dessus, vous pouvez utiliser rest pour obtenir une séquence contenant tous
[Link] 29
les éléments sauf le premier élément d'une séquence existante. Comme first , il appelle seq sur
son argument. Cependant, il n'appelle pas seq sur son résultat! Cela signifie que si vous appelez
rest sur une séquence contenant moins de deux éléments, vous récupérerez () au lieu de nil :
(rest nil)
;;=> ()
(rest '(:foo))
;;=> ()
(rest [:foo])
;;=> ()
(rest #{:foo})
;;=> ()
Si vous voulez récupérer nil quand il n'y a plus d'éléments dans une séquence, vous pouvez
utiliser next au lieu de rest :
(next nil)
;;=> nil
(next '(:foo))
;;=> nil
(next [:foo])
;;=> nil
Vous pouvez utiliser la fonction cons pour créer une nouvelle séquence qui renverra son premier
argument pour le first et son deuxième argument pour le rest :
Clojure fournit une grande bibliothèque de séquences avec de nombreuses fonctions pour gérer
les séquences. L'important à propos de cette bibliothèque est qu'elle fonctionne avec tout ce qui
peut être "séqé", pas seulement les listes. C'est pourquoi le concept d'une séquence est si utile;
cela signifie qu'une seule fonction, comme reduce , fonctionne parfaitement sur n'importe quelle
collection:
[Link] 30
(reduce + [1 2 3])
;;=> 6
L'autre raison pour laquelle les séquences sont utiles est que, puisqu'elles ne requièrent aucune
implémentation particulière du first et du rest , elles permettent des séquences paresseuses dont
les éléments ne sont réalisés que lorsque cela est nécessaire.
Étant donné une expression qui créerait une séquence, vous pouvez envelopper cette expression
dans la macro lazy-seq pour obtenir un objet qui agit comme une séquence, mais n'évaluera
réellement cette expression que lorsque la fonction seq le demandera, à quel point il va mettre en
cache le résultat de l'expression et en avant first et rest les appels vers le résultat mis en cache.
Pour les séquences finies, une séquence paresseuse agit généralement comme une séquence
équivalente:
(defn eager-fibonacci [a b]
(cons a (eager-fibonacci b (+' a b))))
(defn lazy-fibonacci [a b]
(lazy-seq (cons a (lazy-fibonacci b (+' a b)))))
Vecteurs
[]
;;=> []
[:foo]
;;=> [:foo]
[:foo :bar]
;;=> [:foo :bar]
[1 (+ 1 1) 3]
;;=> [1 2 3]
[Link] 31
En plus de la syntaxe littérale, vous pouvez également utiliser la fonction vector pour construire un
vecteur:
(vector)
;;=> []
(vector :foo)
;;=> [:foo]
(vector 1 (+ 1 1) 3)
;;=> [1 2 3]
Vous pouvez tester si quelque chose est un vecteur en utilisant le vector? prédicat:
(vector? [])
;;=> true
(vector? nil)
;;=> false
(vector? 42)
;;=> false
(vector? :foo)
;;=> false
(conj [] :foo)
;;=> [:foo]
(count [])
;;=> 0
[Link] 32
(peek [])
;;=> nil
(peek [:foo])
;;=> :foo
Vous pouvez obtenir un nouveau vecteur sans le dernier élément en utilisant pop :
(pop [:foo])
;;=> []
Notez que si vous essayez de faire apparaître un vecteur vide, vous obtiendrez une
IllegalStateException :
(pop [])
;; [Link]: Can't pop empty vector
Contrairement aux listes, les vecteurs sont indexés. Vous pouvez obtenir un élément d'un vecteur
par index dans le temps "constant" en utilisant get :
De plus, les vecteurs eux-mêmes sont des fonctions qui prennent un index et renvoient l'élément
à cet index:
([:foo :bar] 0)
;;=> :foo
([:foo :bar] 1)
;;=> :bar
Cependant, si vous appelez un vecteur avec un index non valide, vous obtiendrez une
IndexOutOfBoundsException au lieu de nil :
[Link] 33
([:foo :bar] 2)
;; [Link]:
Vous pouvez obtenir un nouveau vecteur avec une valeur différente à un index particulier en
utilisant assoc :
Si vous passez un index égal au count de vecteurs, Clojure ajoutera l'élément comme si vous
aviez utilisé conj . Toutefois, si vous transmettez un index négatif ou supérieur au count , vous
obtenez une IndexOutOfBoundsException :
Vous pouvez obtenir une séquence des éléments dans un vecteur en utilisant seq :
(seq [])
;;=> nil
(seq [:foo])
;;=> (:foo)
Comme les vecteurs sont indexés, vous pouvez également obtenir une séquence inversée des
éléments d'un vecteur en utilisant rseq :
(rseq [])
;;=> nil
(rseq [:foo])
;;=> (:foo)
Notez que, bien que toutes les listes soient des séquences et que les séquences soient affichées
de la même manière que les listes, toutes les séquences ne sont pas des listes!
'(:foo :bar)
;;=> (:foo :bar)
[Link] 34
(seq [:foo :bar])
;;=> (:foo :bar)
Ensembles
Comme les cartes, les ensembles sont associatifs et non ordonnés. Contrairement aux cartes, qui
contiennent des correspondances entre les clés et les valeurs, elles définissent essentiellement la
correspondance entre les clés et elles-mêmes.
#{}
;;=> #{}
#{:foo}
;;=> #{:foo}
#{:foo :bar}
;;=> #{:bar :foo}
Comme pour les cartes, l'ordre dans lequel les éléments apparaissent dans un ensemble littéral
n'a pas d'importance:
Vous pouvez tester si quelque chose est un ensemble en utilisant l' set? prédicat:
(set? #{})
;;=> true
(set? #{:foo})
;;=> true
(set? nil)
;;=> false
(set? 42)
;;=> false
(set? :foo)
;;=> false
[Link] 35
Vous pouvez tester si une carte contient un élément donné dans le temps "constant" en utilisant le
contains? prédicat:
De plus, les ensembles eux-mêmes sont des fonctions qui prennent un élément et renvoient cet
élément s'il est présent dans l'ensemble, ou nil s'il ne l'est pas:
(#{} :foo)
;;=> nil
(#{:foo} :foo)
;;=> :foo
(#{:foo} :bar)
;;=> nil
(#{} nil)
;;=> nil
(#{nil} nil)
;;=> nil
Vous pouvez utiliser conj pour obtenir un ensemble contenant tous les éléments d'un ensemble
existant, plus un élément supplémentaire:
Vous pouvez utiliser disj pour obtenir un ensemble disj tous les éléments d'un ensemble existant,
moins un élément:
[Link] 36
;;=> #{}
(count #{})
;;=> 0
Vous pouvez obtenir une séquence de tous les éléments d'un ensemble en utilisant seq :
(seq #{})
;;=> nil
(seq #{:foo})
;;=> (:foo)
Plans
Contrairement à la liste, qui est une structure de données séquentielle, et le vecteur, qui est à la
fois séquentiel et associatif, la carte est exclusivement une structure de données associative. Une
carte consiste en un ensemble de correspondances entre les clés et les valeurs. Toutes les clés
sont uniques, donc les cartes prennent en charge la recherche "constante" entre les clés et les
valeurs.
{}
;;=> {}
{:foo :bar}
;;=> {:foo :bar}
Chaque paire de deux éléments est une paire clé-valeur. Ainsi, par exemple, la première carte ci-
dessus n'a pas de correspondance. Le second a un mapping, de la clé :foo à la valeur :bar . Le
[Link] 37
troisième a deux mappages, un de la clé :foo à la valeur :bar , et un de la clé :baz à la valeur :qux
. Les cartes sont intrinsèquement non ordonnées, donc l'ordre dans lequel les correspondances
apparaissent n'a pas d'importance:
Vous pouvez tester si quelque chose est une carte en utilisant la map? prédicat:
(map? {})
;;=> true
(map? nil)
;;=> false
(map? 42)
;;=> false
(map? :foo)
;;=> false
Vous pouvez tester si une carte contient une clé donnée dans le temps "constant" en utilisant le
contains? prédicat:
[Link] 38
(get {:foo :bar :baz :qux} :foo)
;;=> :bar
De plus, les cartes elles-mêmes sont des fonctions qui prennent une clé et renvoient la valeur
associée à cette clé:
Vous pouvez obtenir une entrée de carte complète (clé et valeur ensemble) en tant que vecteur à
deux éléments en utilisant find :
[Link] 39
(find {:foo :bar :baz :qux} :qux)
;;=> nil
Vous pouvez extraire la clé ou la valeur d'une entrée de carte en utilisant la key ou val
respectivement:
Notez que, bien que toutes les entrées de carte Clojure soient des vecteurs, tous les vecteurs ne
sont pas des entrées de carte. Si vous essayez d'appeler key ou val sur quelque chose qui n'est
pas une entrée de carte, vous obtiendrez une ClassCastException :
Vous pouvez tester si quelque chose est une entrée de carte en utilisant l' map-entry? prédicat:
Vous pouvez utiliser assoc pour obtenir une carte ayant toutes les mêmes paires clé-valeur qu'une
carte existante, avec un mappage ajouté ou modifié:
[Link] 40
Vous pouvez utiliser dissoc pour obtenir une carte ayant toutes les mêmes paires clé-valeur
qu'une carte existante, avec éventuellement un mappage supprimé:
(count {})
;;=> 0
Vous pouvez obtenir une séquence de toutes les entrées dans une carte en utilisant seq :
(seq {})
;;=> nil
Encore une fois, les cartes ne sont pas ordonnées, de sorte que l'ordre des éléments dans une
séquence obtenue en appelant seq sur une carte n'est pas défini.
Vous pouvez obtenir une séquence de seulement les clés ou simplement les valeurs dans une
carte en utilisant respectivement des keys ou des vals :
(keys {})
;;=> nil
[Link] 41
(keys {:foo :bar :baz :qux})
;;=> (:foo :baz)
(vals {})
;;=> nil
Clojure 1.9 ajoute une syntaxe littérale pour représenter de manière plus concise une carte où les
clés partagent le même espace de noms. Notez que la carte dans les deux cas est identique (la
carte ne "connaît" pas l'espace de nommage par défaut), ceci est simplement une commodité
syntaxique.
[Link] 42
Chapitre 9: Configuration de votre
environnement de développement
Examples
Table lumineuse
Light Table est un bon éditeur pour apprendre, expérimenter et exécuter des projets Clojure.
Vous pouvez également exécuter des projets lein / boot en ouvrant le fichier [Link] . Il va
charger toutes les dépendances du projet.
Il prend en charge l'évaluation en ligne, les plug-ins et bien plus encore. Il n'est donc pas
nécessaire d'ajouter des instructions d'impression et de vérifier la sortie dans la console. Vous
pouvez exécuter des lignes individuelles ou des blocs de code en appuyant sur Ctrl ctrl + enter .
Pour exécuter un code partiel, sélectionnez le code et appuyez sur ctrl + enter . Vérifiez la
capture d'écran suivante pour savoir comment utiliser Light Table pour apprendre et tester le code
Clojure.
Des binaires pré-construits de Light Table peuvent être trouvés ici . Aucune autre configuration
n'est requise.
[Link] 43
Light Table est capable de localiser automatiquement votre projet Leiningen et d’évaluer votre
code. Si vous n'avez pas installé Leiningen, installez-le en suivant les instructions ci- dessous .
Documentation: [Link]
Emacs
Pour configurer Emacs afin qu'il fonctionne avec Clojure, installez clojure-mode et cider package à
partir de melpa:
Maintenant, lorsque vous ouvrez un fichier .clj , exécutez Mx cider-jack-in pour vous connecter à
une REPL. Alternativement, vous pouvez utiliser Cu Mx (cider-jack-in) pour spécifier le nom d'un
projet lein ou boot sans avoir à visiter aucun fichier. Vous devriez maintenant pouvoir évaluer les
expressions dans votre fichier en utilisant Cx Ce .
Éditer du code dans des langages de type lisp est beaucoup plus confortable avec un plugin
d'édition compatible avec Paren. Emacs a plusieurs bonnes options.
• pareditUn mode d'édition classique de Lisp qui a une courbe d'apprentissage plus raide,
mais qui fournit beaucoup de puissance une fois maîtrisé.
• smartparens Un nouveau projet avec des objectifs et une utilisation similaires à paredit , mais
offre également des capacités réduites avec les langages non-Lisp.
• parinfer Un mode d'édition Lisp beaucoup plus simple qui opère principalement par
inférence d'imbrication paren appropriée à partir de l'indentation.
L'installation est plus parinfer-mode , consultez la page Github pour le parinfer-mode pour les
instructions de configuration .
Atome
[Link] 44
apm install parinfer
apm install language-clojure
apm install proto-repl
Après avoir redémarré IDEA, Cursive devrait être prêt à l'emploi. Suivez le guide de l' utilisateur
pour affiner l'apparence, les raccourcis clavier, le style de code, etc.
Note: Comme IntelliJ , Cursive est un produit commercial, avec une période d’évaluation de 30
jours. Contrairement à IntelliJ , il n’a pas d’édition communautaire. Des licences non
commerciales gratuites sont disponibles pour les particuliers à des fins non commerciales, y
compris le piratage personnel, le logiciel libre et le travail d'étudiant. La licence est valable 6 mois
et peut être renouvelée.
Spacemacs + CIDER
Spacemacs est une distribution d’emacs livrée avec de nombreux paquets préconfigurés et faciles
à installer. En outre, il est très convivial pour ceux qui sont familiers avec le style d'édition vim.
Spacemacs fournit une couche de Clojure basée sur CIDER .
Pour l'installer et le configurer pour l'utiliser avec Clojure, installez d'abord emacs. Faites ensuite
une sauvegarde de vos configurations précédentes:
$ mv ~/.emacs.d ~/.[Link]
Maintenant, ouvrez emacs. Il vous posera quelques questions concernant vos préférences.
Ensuite, il télécharge plus de paquets et configure vos emacs. Après que les spacemacs soient
installés, vous êtes prêt à ajouter le support de Clojure. Appuyez sur SPC fed pour ouvrir votre
fichier .spacemacs pour la configuration. Trouvez dotspacemacs-configuration-layers dans le fichier,
sous dotspacemacs-configuration-layers se trouve un paren ouvert. Partout entre les parens dans
un nouveau type de ligne clojure .
(defun dotspacemacs/layers ()
(setq-default
;; ...
dotspacemacs-configuration-layers
'(clojure
;; ...
)
;; ...
))
[Link] 45
Appuyez sur SPC fe R pour sauvegarder et installer le calque. Maintenant, dans n'importe .clj
fichier .clj si vous appuyez sur , si spacemacs essaiera de générer une nouvelle connexion
REPL cloure à votre projet, et si elle réussit, elle apparaîtra dans la barre d'état, puis vous pourrez
appuyer sur , ss pour ouvrir un nouveau tampon REPL pour évaluer vos codes.
Pour plus d'informations sur spacemacs et cidre contacter leurs documentations. Documents
spacemacs , documents sur le cidre
Vim
1. vim-clojure-static (si vous avez un vim plus ancien que 7.3.803, les nouvelles versions sont
livrées avec)
2. vim-clojure-highlight
[Link] 46
Chapitre 10: [Link]
Examples
opérations de base du canal: création, mise en place, prise, fermeture et
tampons.
consiste à créer des processus qui prennent des valeurs et placent des valeurs dans
[Link]
des canaux .
Vous pouvez mettre n'importe quelle valeur (chaînes, nombres, cartes, collections, objets, même
d'autres canaux, etc.) dans un canal, sauf le nil :
;; WON'T WORK
(a/>!! my-channel nil)
=> IllegalArgumentException Can't put nil on channel
[Link] 47
)
A l'intérieur d'un bloc (go ...) , vous pouvez et devez utiliser a/>! au lieu d' a/>!! :
Le comportement logique sera le même a/>!! , mais seul le processus logique de la goroutine
sera bloqué à la place du thread OS réel.
;; NEVER DO THIS
(a/go
(a/>!! ch :item))
;; creating a channel
(def ch (a/chan 3))
;; putting some items in it
(do
(a/>!! ch :item-1)
(a/>!! ch :item-2)
(a/>!! ch :item-3))
;; taking a value
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
Si aucun élément n'est disponible dans le canal, a/<!! va bloquer le thread actuel jusqu'à ce
qu'une valeur soit placée dans le canal (ou que le canal soit fermé, voir plus loin):
(def ch (a/chan))
(a/<!! ch) ;; blocks until another process puts something into ch or closes it
A l'intérieur d'un bloc (go ...) , vous pouvez et devez utiliser a/<! au lieu d' a/<!! :
Le comportement logique sera le même a/<!! , mais seul le processus logique de la goroutine
sera bloqué à la place du thread OS réel.
;; NEVER DO THIS
(a/go
(a/<!! ch))
[Link] 48
Canaux de fermeture
Vous fermez une chaîne avec a/close! :
(a/close! ch)
Une fois qu'un canal est fermé et que toutes les données du canal ont été épuisées, les prises
renvoient toujours nil :
;; taking from ch will return the items that were put in it, then nil
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
;; once the channel is closed, >!! will have no effect on the channel:
(a/>!! ch :item-3)
=> false ;; false means the put did not succeed
(a/<!! ch) ;; => nil
(a/put! ch :item)
(a/put! ch :item (fn once-put [closed?] ...)) ;; callback function, will receive
En ClojureScript, depuis le blocage du thread en cours n'est pas possible, a/>!! n'est pas
supporté et put! est le seul moyen de placer des données dans un canal en dehors d'un bloc (go)
.
[Link] 49
Avec les tampons de dépôt et de glissement, ne bloque jamais, mais lorsque le tampon est plein,
vous perdez des données. Le tampon de suppression perd les dernières données ajoutées, tandis
que les tampons glissants perdent les premières données ajoutées.
[Link] 50
Chapitre 11: Correspondance de motif avec
[Link]
Remarques
La bibliothèque [Link] implémente un algorithme de compilation de correspondance de
modèle qui utilise la notion de "nécessité" à partir de la correspondance de modèle paresseux.
Examples
Littéraux correspondants
(let [x true
y true
z true]
(match [x y z]
[_ false true] 1
[false true _ ] 2
[_ _ false] 3
[_ _ true] 4))
;=> 4
(let [v [1 2 3]]
(match [v]
[[1 1 1]] :a0
[[1 _ 1]] :a1
[[1 2 _]] :a2)) ;; _ is used for wildcard matching
;=> :a2
;=> :a1
(match [['asymbol]]
[['asymbol]] :success)
[Link] 51
;=> :success
[Link] 52
Chapitre 12: Démarrer avec le développement
web
Examples
Créer une nouvelle application Ring avec http-kit
Ring est une API standard de facto pour les applications HTTP clojure, similaire à Ruby's Rack et
WSGI de Python.
(ns [Link]
(:gen-class)
(:require [[Link] :refer [run-server]]))
Définir le gestionnaire de demande de sonnerie. Les gestionnaires de requêtes ne sont que des
fonctions allant de la requête à la réponse et la réponse est juste une carte:
Ici, il suffit de retourner 200 OK avec le même contenu pour toute demande.
(defn -main
[& args]
(run-server app {:port 8080}))
[Link] 53
Luminus est un micro-framework Clojure basé sur un ensemble de bibliothèques légères. Il vise à
fournir une plate-forme robuste, évolutive et facile à utiliser. Avec Luminus, vous pouvez vous
concentrer sur le développement de votre application comme vous le souhaitez sans aucune
distraction. Il a également une très bonne documentation qui couvre certains des sujets de majour
Il est très facile de commencer avec le luminus. Créez simplement un nouveau projet avec les
commandes suivantes:
lein new luminus myapp créera une application en utilisant le modèle de profil par défaut. Toutefois,
si vous souhaitez ajouter des fonctionnalités supplémentaires à votre modèle, vous pouvez ajouter
des conseils de profil pour les fonctionnalités étendues.
Serveurs Web
• + aleph - ajoute le support du serveur Aleph au projet
• + jetée - ajoute le soutien Jetty au projet
• + http-kit - ajoute le serveur Web HTTP Kit au projet
bases de données
• + h2 - ajoute un espace de noms [Link] et des dépendances H2 db
• + sqlite - ajoute un espace de noms [Link] et des dépendances SQLite db
• + postgres - ajoute un espace de nommage [Link] et ajoute des dépendances PostreSQL
• + mysql - ajoute un espace de noms [Link] et ajoute des dépendances MySQL
• + mongodb - ajoute les dépendances de l'espace de noms [Link] et de MongoDB
• + datomic - ajoute un espace de noms [Link] et des dépendances Datomic
divers
• + auth - ajoute un middleware de dépendance et d'authentification Buddy
• + auth-jwe - ajoute la dépendance Buddy avec le backend JWE
• + cider - ajoute le support de CIDER en utilisant le plugin CIDER nREPL
• + cljs - ajoute le support [ClojureScript] [cljs] avec Reagent
• + re-frame - ajoute le support [ClojureScript] [cljs] avec re-frame
• + concombre - un profil pour concombre avec clj-webdriver
• + swagger - ajoute la prise en charge de Swagger-UI à l'aide de la bibliothèque compojure-
api
• + sassc - ajoute le support pour les fichiers SASS / SCSS en utilisant le compilateur en ligne
de commande SassC
• + service - créer une application de service sans la configuration frontale telle que les
[Link] 54
modèles HTML
• + war - ajoute la prise en charge de la création d'archives WAR pour un déploiement sur des
serveurs tels qu'Apache Tomcat (ne doit PAS être utilisé pour les applications Immutant
exécutées sur WildFly)
• + site - crée un modèle pour le site en utilisant la base de données spécifiée (H2 par défaut)
et ClojureScript
Pour ajouter un profil, transmettez-le simplement comme argument après le nom de votre
application, par exemple:
Vous pouvez également mélanger plusieurs profils lors de la création de l'application, par
exemple:
[Link] 55
Chapitre 13: Déstructuration Clojure
Examples
Destruction d'un vecteur
Ensuite, par exemple dans un bloc let , vous pouvez extraire les valeurs du vecteur très
succinctement comme suit:
Ensuite, par exemple, dans un bloc let, vous pouvez extraire les valeurs de la carte très
succinctement comme suit:
Notez que les valeurs extraites dans chaque mappage sont à gauche et les clés auxquelles elles
sont associées sont à droite.
Si vous souhaitez déstructurer des valeurs vers des liaisons ayant les mêmes noms que les clés,
vous pouvez utiliser ce raccourci:
Si vos clés sont des chaînes, vous pouvez utiliser presque la même structure:
[Link] 56
Et de même pour les symboles:
Si vous souhaitez déstructurer une carte imbriquée, vous pouvez imbriquer les formes de liaison
expliquées ci-dessus:
(def data
{:foo {:a 1
:b 2}
:bar {:a 10
:b 20}})
Et vous voulez extraire les 3 premiers éléments et obtenir les éléments restants sous forme de
séquence. Cela peut être fait comme suit:
Parfois, vous voulez détruire la clé sous une carte qui pourrait ne pas être présente dans la carte,
mais vous voulez une valeur par défaut pour la valeur déstructurée. Vous pouvez le faire de cette
façon:
[Link] 57
(let [{a :a
b :b
:keys [c d]
:or {a 1
c 2}} my-map]
(println a b c d))
;= 3 4 2 nil
La destruction fonctionne dans de nombreux endroits, ainsi que dans la liste des paramètres
d'une fn:
(my-func [1 2 3]) ;= 5
(my-func (range 5)) ;= 3
La destruction fonctionne également pour la construction & rest dans la liste des paramètres:
(my-func2 1 2 3) ;= 5
(apply my-func2 (range 5)) ;= 3
La destruction vous permet également d’interpréter une séquence comme une carte:
C'est utile pour définir des fonctions avec des paramètres nommés :
(my-func 1 2) ;= 1 2 3 4
(my-func 3 4 :c 5 :d 6) ;= 3 4 5 6
Vue d'ensemble
La destruction vous permet d'extraire des données de divers objets dans des variables distinctes.
Dans chaque exemple ci-dessous, chaque variable est affectée à sa propre chaîne ( a = "a" , b =
"b" , & c.)
[Link] 58
Type Exemple Valeur des data / commentaire
vec
(let [[[ab] [cd]] data ...) [["a" "b"] ["c" "d"]]
imbriqué
- (let [{:keys [abc]} data Lorsque les variables sont nommées d'après les
alternative: ...) clés.
Conseils:
• Les valeurs par défaut peuvent être fournies en utilisant :or , sinon la valeur par défaut est
nil
• Utilisez & rest pour stocker un seq de toutes les valeurs supplémentaires au rest , sinon les
valeurs supplémentaires sont ignorées
• Une utilisation commune et utile de la déstructuration concerne les paramètres de fonction
• Vous pouvez affecter des parties non désirées à une variable jetable (classiquement: _ )
Parfois, lors de la déstructuration des cartes, vous souhaitez lier les valeurs déstructurées à leur
nom de clé respectif. Selon la granularité de la structure de données, l'utilisation du schéma de
déstructuration standard peut être un peu verbeux .
Disons que nous avons un enregistrement basé sur la carte comme ceci:
ici, la structure des données est assez simple avec seulement 3 slots ( prénom, nom, pays ) mais
imaginez la lourdeur si nous devions répéter tous les noms de clés deux fois pour une structure de
données plus granulaire (avec bien plus de slots que 3) .
Au lieu de cela, une meilleure façon de gérer cela consiste à utiliser :keys (puisque nos clés sont
des mots - clés ici) et à sélectionner le nom de la clé que nous aimerions lier ainsi:
[Link] 59
La même logique intuitive s'applique à d'autres types de clés comme les symboles (en utilisant
:syms ) et les anciennes chaînes simples (en utilisant :strs )
(defn print-some-items
[[a b :as xs]]
(println a)
(println b)
(println xs))
(print-some-items [2 3])
2
3
[2 3]
L'argument est déstructuré et les éléments 2 et 3 sont affectés aux symboles a et b . L'argument
d'origine, le vecteur entier [2 3] , est également affecté au symbole xs .
[Link] 60
Chapitre 14: Effectuer des opérations
mathématiques simples
Introduction
Voici comment vous ajouteriez des nombres dans la syntaxe Clojure. Comme la méthode est le
premier argument de la liste, nous évaluons la méthode + (ou addition) sur le reste des arguments
de la liste.
Remarques
L'exécution d'opérations mathématiques est la base de la manipulation des données et de
l'utilisation des listes. Par conséquent, comprendre comment cela fonctionne est essentiel pour
progresser dans la compréhension de Clojure.
Examples
Exemples mathématiques
;; returns 3
(+ 1 2)
;; returns 300
(+ 50 210 40)
;; returns 2
(/ 8 4)
[Link] 61
Chapitre 15: Emacs CIDER
Introduction
CIDER est l'acronyme de C lojure (script) I nteractive D veloppement E nvironment que R
troupeaux. C'est une extension à emacs. CIDER vise à fournir un environnement de
développement interactif au programmeur. CIDER est construit sur nREPL, un serveur REPL en
réseau et SLIME a servi d'inspiration principale pour CIDER.
Examples
Évaluation de la fonction
La fonction CIDER cider-eval-last-sexp peut être utilisée pour exécuter le code lors de l'édition du
code à l'intérieur du tampon. Cette fonction est par défaut liée à Cx Ce ou Cx Ce .
Par exemple:
(defn say-hello
[username]
(format "Hello, my name is %s" username))
(defn introducing-bob
[]
(say-hello "Bob")) => "Hello, my name is Bob"
Exécuter Cx Ce ou Cc Ce alors que votre curseur est juste avant la fin paren de l'appel de la
fonction say-hello affichera la chaîne Hello, my name is Bob .
Jolie impression
La fonction CIDER cider-insert-last-sexp-in-repl peut être utilisée pour exécuter le code lors de
l'édition du code à l'intérieur du tampon et obtenir une sortie assez imprimée dans un tampon
différent. Cette fonction est par défaut liée à Cc Cp .
Par exemple
[Link] 62
(def databases {:database1 {:password "password"
:database "test"
:port "5432"
:host "localhost"
:user "username"}
(defn get-database-config
[]
databases)
(get-database-config)
Effectuer Cc alors que votre curseur est juste avant la fin du paren de l'appel de la fonction get-
Cp
database-config affichera la jolie carte imprimée dans un nouveau tampon popup.
{:database1
{:password "password",
:database "test",
:port "5432",
:host "localhost",
:user "username"},
:database2
{:password "password",
:database "different_test_db",
:port "5432",
:host "localhost",
:user "vader"}}
[Link] 63
Chapitre 16: Interop Java
Syntaxe
• . vous permet d'accéder aux méthodes d'instance
• .- vous permet d'accéder aux champs d'instance
• .. macro en expansion à plusieurs invocations imbriquées de .
Remarques
En tant que langage hébergé, Clojure fournit un excellent support d'interopérabilité avec Java. Le
code Clojure peut également être appelé directement depuis Java.
Examples
Appeler une méthode d'instance sur un objet Java
Vous pouvez appeler des méthodes d'instance avec des arguments comme ceci:
(.substring "hello" 0 2)
;;=> "he"
([Link]. 0 1)
;;=> => #object[[Link] 0x3776d535 "[Link][x=0,y=1]"]
Ou
[Link] 64
(new [Link] 0 1)
;;=> => #object[[Link] 0x3776d535 "[Link][x=0,y=1]"]
(System/currentTimeMillis)
;;=> 1469493415265
Vous pouvez appeler une fonction Clojure à partir du code Java en recherchant la fonction et en
l'appelant:
Cela recherche la fonction * depuis l' [Link] noms [Link] et l'invoque avec les
arguments 2 & 2.
[Link] 65
Chapitre 17: Les fonctions
Examples
Définition des fonctions
(defn welcome
"Return a welcome message to the world"
...)
(defn welcome
"Return a welcome message"
[name]
...)
(defn welcome
"Return a welcome message"
[name]
(str "Hello, " name "!"))
En l'appelant:
"Hello, World!"
Paramètres et Arity
Les fonctions de clojure peuvent être définies avec zéro ou plusieurs paramètres.
(defn welcome
"Without parameters"
[Link] 66
[]
"Hello!")
(defn square
"Take one parameter"
[x]
(* x x))
(defn multiplier
"Two parameters"
[x y]
(* x y))
Arity
Le nombre d'arguments pris par une fonction Les fonctions prennent en charge la surcharge
d'arity , ce qui signifie que les fonctions de Clojure permettent plusieurs "ensembles" d'arguments.
(defn sum-args
;; 3 arguments
([x y z]
(+ x y z))
;; 2 arguments
([x y]
(+ x y))
;; 1 argument
([x]
(+ x 1)))
Les arités n'ont pas à faire le même travail, chaque arité peut faire quelque chose sans rapport:
(defn do-something
;; 2 arguments
([first second]
(str first " " second))
;; 1 argument
([x]
(* x x x)))
Une fonction Clojure peut être définie pour prendre un nombre arbitraire d'arguments, en utilisant
le symbole & dans sa liste d'arguments. Tous les arguments restants sont collectés sous forme de
séquence.
Appel:
[Link] 67
=> (sum 1 11 23 42)
77
Il existe deux manières de définir une fonction anonyme: la syntaxe complète et un raccourci.
(fn [x y] (+ x y))
Cette expression évalue une fonction. Toute syntaxe que vous pouvez utiliser avec une fonction
définie avec defn ( & , argument de déstructuration, etc.), vous pouvez également faire avec le
formulaire fn . defn est en fait une macro qui ne fait que (def (fn ...)) .
#(+ %1 %2)
C'est la notation abrégée. En utilisant la notation abrégée, vous n'avez pas à nommer
explicitement les arguments; ils se verront attribuer les noms %1 , %2 , %3 et ainsi de suite en
fonction de l'ordre dans lequel ils sont passés. Si la fonction n'a qu'un seul argument, son
argument s'appelle simplement % .
Il prend un nombre variable d'arguments et renvoie true si chacun d'entre eux est pair:
[Link] 68
(#(every? even? %&) 1 2 4 6)
;; false
Malgré l'apparente contradiction, il est possible d'écrire une fonction anonyme nommée en
incluant un nom, comme dans l'exemple suivant. Ceci est particulièrement utile si la fonction doit
s'appeler elle-même mais aussi dans les traces de pile.
[Link] 69
Chapitre 18: Macros
Syntaxe
• Le ' symbole utilisé dans l'exemple macroexpand est juste du sucre syntaxique pour la quote
opérateur. Vous pourriez avoir écrit (macroexpand (quote (infix 1 + 2))) place.
Remarques
Les macros ne sont que des fonctions qui s'exécutent au moment de la compilation, c'est-à-dire
pendant l'étape d' eval dans une boucle read-eval-print-loop .
Les macros de lecteur sont une autre forme de macro qui est développée au moment de la
lecture, plutôt que lors de la compilation.
• Alpha-renaming, Puisque la macro est développée, le conflit de nom de liaison peut survenir.
Le conflit de liaison n'est pas très intuitif à résoudre lors de l'utilisation de la macro. C'est
pourquoi, chaque fois qu'une macro ajoute une liaison à la portée, il est obligatoire d'utiliser
le # à la fin de chaque symbole.
Examples
Simple Infix Macro
Clojure utilise la notation préfixée, à savoir: l'opérateur vient avant ses opérandes.
(+ 1 2)
;; => 3
Les macros vous permettent de manipuler le langage Clojure dans une certaine mesure. Par
exemple, vous pouvez implémenter une macro qui vous permet d'écrire du code en notation infixe
(par exemple, 1 + 2 ):
• defmacro est un formulaire spécial que vous utilisez pour définir une macro.
• infix est le nom de la macro que nous définissons.
• [first-operand operator second-operand] sont les paramètres que cette macro s'attend à
[Link] 70
recevoir lorsqu'elle est appelée.
• (list operator first-operand second-operand)est le corps de notre macro. Il crée simplement
une list avec les valeurs des paramètres fournis à la macro infix et la retourne.
defmacroest une forme particulière car elle se comporte un peu différemment des autres
constructions Clojure: ses paramètres ne sont pas immédiatement évalués (quand on appelle la
macro). C'est ce qui nous permet d'écrire quelque chose comme:
(infix 1 + 2)
;; => 3
La macro infix étendra les arguments 1 + 2 dans (+ 1 2) , qui est un formulaire Clojure valide
pouvant être évalué.
Si vous voulez voir ce que la macro infix génère, vous pouvez utiliser l'opérateur macroexpand :
macroexpand , implicite par son nom, développera la macro (dans ce cas, elle utilisera la macro
infix pour transformer 1 + 2 en (+ 1 2) ) mais ne permettra pas d’évaluer le résultat de l’extension
de la macro par L'interprète de Clojure.
(defmacro and
"Evaluates exprs one at a time, from left to right. If a form
returns logical false (nil or false), and returns that value and
doesn't evaluate any of the other expressions, otherwise it returns
the value of the last expr. (and) returns true."
{:added "1.0"}
([] true)
([x] x)
([x & next]
`(let [and# ~x]
(if and# (and ~@next) and#))))
• `appelé syntaxe-citation est comme (quote) , mais récursif: il provoque (let …) , (if …) , etc.
à ne pas évaluer lors de l'expansion de la macro mais à produire tel quel
• ~ aka unquote annule les guillemets syntaxiques pour un formulaire unique dans une forme
citée avec la syntaxe. Donc, la valeur de x est sortie lors du développement de la macro (au
lieu de sortir le symbole x )
• ~@ aka unquote-splicing est comme unquote mais prend un argument de liste et le
développe, chaque élément de la liste se sépare
• # ajoute un identifiant unique aux symboles pour éviter les conflits de noms. Il ajoute le
même identifiant pour le même symbole à l'intérieur de l'expression citée entre syntaxes,
and# inside let et and# inside if obtiendra le même nom
[Link] 71
Lire Macros en ligne: [Link]
[Link] 72
Chapitre 19: Macros de filetage
Introduction
Également appelées macros à flèche, les macros de threads convertissent les appels de fonctions
imbriqués en un flux linéaire d'appels de fonctions.
Examples
Fil Dernier (- >>)
Cette macro donne la sortie d'une ligne donnée en tant que dernier argument de l'appel de
fonction de ligne suivant. Par exemple
(->> 2
(+ 3)
(str)
(prn))
Cette macro donne la sortie d'une ligne donnée en tant que premier argument de l'appel de
fonction de ligne suivant. Par exemple
(-> {:a 1}
(assoc :b 1) ;;(assoc map key val)
(rename-keys {:b :new-b})) ;;(rename-keys map key-newkey-map)
Thread as (as->)
C'est une alternative plus flexible au premier thread ou au dernier thread. Il peut être inséré
n'importe où dans la liste des paramètres de la fonction.
(as-> [1 2] x
(map #(+ 1 %) x)
(if (> (count x) 2) "Large" "Small"))
[Link] 73
Lire Macros de filetage en ligne: [Link]
[Link] 74
Chapitre 20: Opérations sur les fichiers
Examples
Vue d'ensemble
Lire un fichier en une seule fois (déconseillé pour les gros fichiers):
(slurp "./small_file.txt")
(use '[Link])
(with-open [rdr (reader "./[Link]")]
(line-seq rdr) ; returns lazy-seq
) ; with-open macro calls (.close rdr)
(use '[Link])
(with-open [wrtr (writer "./[Link]" :append true)]
(.write wrtr "2016-07-26 New entry.")
) ; with-open macro calls (.close wrtr)
(use '[Link])
(with-open [wrtr (writer "./[Link]")]
(.write wrtr "Everything in [Link] has been replaced with this text.")
) ; with-open macro calls (.close wrtr)
Remarques:
• Vous pouvez spécifier des URL ainsi que des fichiers
• Les options vers (slurp) et (spit) sont respectivement transmises à [Link]/reader
et /writer .
[Link] 75
Chapitre 21: Transducteurs
Introduction
Les transducteurs sont des composants composables permettant de traiter des données
indépendamment du contexte. Ils peuvent donc être utilisés pour traiter des collections, des flux,
des canaux, etc. sans connaître leurs sources d'entrée ou leurs puits de sortie.
La bibliothèque principale de Clojure a été étendue en 1.7 pour que les fonctions de séquence
telles que carte, filtre, prise, etc. renvoient un transducteur lorsqu'il est appelé sans séquence.
Parce que les transducteurs sont des fonctions avec des contrats spécifiques, ils peuvent être
composés en utilisant la normale comp fonction.
Remarques
Les transducteurs permettent de contrôler la paresse au fur et à mesure de leur consommation.
Par exemple, into est comme on peut s'y attendre, mais la sequence consommera paresseusement
la séquence à travers le transducteur. Cependant, la garantie de paresse est différente. Assez de
la source sera consommée pour produire un élément initialement:
(take 0 (sequence (comp (map #(do (prn '-> %) %)) (remove number?)) (range 5)))
;; -> 0
;; -> 1
;; -> 2
;; -> 3
;; -> 4
;; => ()
Examples
Petit transducteur appliqué à un vecteur
[Link] 76
(transduce xf + [1 2 3 4 5 6 7 8 9 10]))
;; => 30
Cet exemple crée un transducteur affecté au xf local et utilise la transduce pour l'appliquer à
certaines données. Le transducteur en ajoute un à chacune de ses entrées et ne renvoie que les
nombres pairs.
transduce est comme reduce et réduit la collection d'entrée à une valeur unique en utilisant la
fonction + fournie.
Cela se lit comme la dernière macro thread, mais sépare les données d'entrée des calculs.
(->> [1 2 3 4 5 6 7 8 9 10]
(map inc)
(filter even?)
(reduce +))
;; => 30
Application de transducteurs
Appliquer à une collection en réduisant la collection résultante avec une autre fonction:
Créez un canal asynchrone principal qui utilise un transducteur pour filtrer les messages:
Ainsi, les fonctions les plus utilisées sur les cartes et les filtres de Clojure ont été modifiées pour
renvoyer des transducteurs (transformations algorithmiques composables), sinon appelés avec
une collection. Cela signifie:
[Link] 77
(map inc) renvoie un transducteur et le fait aussi (filter odd?)
L'avantage: les fonctions peuvent être composées en une seule fonction par comp, ce qui signifie
traverser la collection une seule fois. Enregistre le temps d'exécution de plus de 50% dans
certains scénarios.
Définition:
Usage:
;; We do this:
(into [] composed-fn [1 8 3 10 5])
;; Output: [9 11]
[Link] 78
Chapitre 22: Vars
Syntaxe
• (valeur du symbole def)
• (valeur de symbole déf "docstring")
• (déclarer symbole_0 symbole_1 symbole_2 ...)
Remarques
Cela ne doit pas être confondu avec (defn) , qui est utilisé pour définir des fonctions.
Examples
Types de variables
• Nombres
Types de nombres:
○ entiers
○ longues (nombre supérieur à 2^31 - 1 )
○ flotteurs (décimaux)
• cordes
• collections
Types de collections:
○ Plans
○ séquences
○ vecteurs
• les fonctions
[Link] 79
Chapitre 23: Vérité
Examples
Vérité
Dans Clojure, tout ce qui n'est pas nil ou false est considéré comme vrai.
Exemples:
Booléens
Toute valeur dans Clojure est considérée comme véridique sauf si elle est false ou nil . Vous
pouvez trouver la véracité d'une valeur avec (boolean value) . Vous pouvez trouver la véracité
d'une liste de valeurs en utilisant (or) , qui renvoie true si des arguments sont vrais, ou (and) qui
renvoie true si tous les arguments sont vrais.
[Link] 80
Crédits
S.
Chapitres Contributeurs
No
Analyse des
2 user2611740
journaux avec clojure
Collections et
8 Alex Miller, Kenogu Labz, nXqd, Sam Estep
séquences
Correspondance de
11 motif avec Kiran
[Link]
Démarrer avec le
12 Emin Tham, kolen, r00tt
développement web
Effectuer des
opérations
14 Jim
mathématiques
simples
[Link] 81
16 Interop Java leeor
[Link] 82