close

Clown

Aller à la navigation Aller à la recherche
clown
Clojure logo.svg
Développeur(s)
Richard Hickey
https://clojure.org/
Informations générales
Extensions courantes clj, cljs, cljc, edn et cljr
Paradigme Langage de programmation fonctionnel et multiparadigme
Apparaît dans 2007
Élaboré par Riche Hickey
Dernière version stable (2022-03-22)
système de typage dynamique , fort
implémentations JVM , CLR , JavaScript
influencé par Lisp , ML , Haskell , Erlang Prolog
Système opératif Multi plateforme
Licence Licence publique Eclipse

Clojure est un dialecte de langage de programmation à usage général de Lisp . Il met un accent particulier sur le paradigme fonctionnel , dans le but (entre autres) de supprimer la complexité associée à la programmation concurrente . Clojure peut être exécuté sur la machine virtuelle Java et la machine virtuelle de la plate-forme .NET , ainsi que compilé en JavaScript .

Principes

Rich Hickey décrit le développement de Clojure comme la recherche d'un langage qu'il n'a pas pu trouver : un lisp fonctionnel par défaut, construit sur un environnement robuste plutôt que sur sa propre plate-forme, et avec une programmation simultanée à l'esprit. [ 1 ]

De même, l'orientation objet est rejetée par principe, offrant une approche dans laquelle les programmes sont exprimés comme l'application de fonctions sur les données, plutôt que comme l'interaction entre des entités mutables qui mélangent la représentation et le comportement des données. D'autre part, des fonctionnalités telles que l'instanciabilité, le polymorphisme et les interfaces font effectivement partie du langage.

Syntaxe

Comme le reste de la famille Lisp, la syntaxe de Clojure est construite sur des expressions symboliques qui sont converties en structures de données par un lecteur avant d'être compilées. Les expressions sont caractérisées par le fait qu'elles sont délimitées par des parenthèses et par leur notation de préfixe, par laquelle le premier membre de chaque liste est appelé en tant que fonction, en passant le reste des membres comme arguments.

Cette particularité, étrange pour les habitués des langages les plus populaires basés sur la syntaxe du langage de programmation C, est à la base de sa flexibilité. Les structures de données telles que maps , sets et vectors ont une expression littérale ; ils ne nécessitent aucune transformation lors de leur incorporation dans l'arbre syntaxique généré par le compilateur. Clojure est un Lisp-1 et n'est pas particulièrement conçu pour être compatible avec d'autres lisps .

Macro

Une macro est un morceau de code qui accepte d'autres expressions comme arguments, sans les évaluer, en les transformant avant de les évaluer. Cela permet l'émergence de "programmes créant des programmes": ajouts au langage - structures de contrôle de flux - ou création d'un langage spécifique à un domaine . Possibilités en principe inatteignables dans d'autres familles de langages sans recourir au développement d'un compilateur .

Le système de macros de Clojure est très similaire à celui de Common Lisp à l'exception que la version de Clojure de l'arrière-guillemet (appelée "guillemet syntaxique") qualifie les symboles avec l'espace de noms auquel ils appartiennent. Cela permet d'éviter une capture involontaire puisque les liaisons qualifiées par le nom sont interdites. Il est possible de forcer l'expansion d'une macro qui les capture mais cela doit être fait explicitement. Clojure interdit également la reliure des noms globaux dans d'autres espaces de noms qui ont été importés dans l'espace actuel.

Une autre caractéristique de la citation syntaxique est qu'elle permet un système de modèles , dans lequel vous pouvez spécifier quels membres d'une liste doivent être évalués à l'aide des opérateurs unquote (~) et unquote-splice (~@), conduisant à des macros plus concises et maniable.

Fonctionnalités linguistiques

  • Développement dynamique avec une console d'évaluation ( REPL : read eval print loop ).
  • Représentation des fonctions sous forme de valeurs, et préférence pour la récursivité et l'utilisation de fonctions d'ordre supérieur par rapport à l' itération basée sur les effets secondaires .
  • Nombres de précision arbitraires et représentation littérale de fractions, générés sur des divisions non entières.
  • Séquences avec évaluation paresseuse (les éléments de la séquence ne sont pas calculés tant qu'ils ne sont pas nécessaires, ce qui permet de représenter des ensembles potentiellement infinis).
  • Système intégré de structures de données persistantes et immuables.
  • Contrôle d'état (ensemble de valeurs qu'une entité peut acquérir au fil du temps) dans des situations de concurrence par le biais de systèmes transactionnels, d'agents et de liaisons locales .
  • Interaction avec Java : En étant compilées en bytecode JVM , les applications écrites en Clojure peuvent être facilement intégrées dans des serveurs d'applications ou d'autres environnements Java avec peu de complexité supplémentaire. Toutes les interfaces possibles au niveau de la classe, de la structure des données et de la concurrence sont implémentées par défaut pour minimiser les efforts nécessaires pour atteindre cette portabilité.

Exemples

Salut le monde . Notez qu'en raison de la nature du REPL, une commande d' impression n'est pas nécessaire .

"Salut monde!"

Un générateur de numéros uniques et consécutifs qui prend en charge les appels simultanés :

( let  [i  ( atom  0 ) ] 
  ( defn  generate-unique-id 
    "Renvoie un identifiant numérique différent pour chaque appel." 
    [] 
    ( swap!  i  inc )))

Une sous-classe anonyme de java.io.Writerqui n'écrit nulle part, et une macro qui l'utilise pour faire taire toutes les expressions évaluées avec elle.

( def  bit-bucket-writer 
  ( proxy  [java.io.Writer]  [] 
    ( write  [buf]  nil ) 
    ( close  []     nil ) 
    ( flush  []     nil )))

( defmacro  noprint 
  "Évalue l'expression donnée avec toutes les impressions sur *out* en sourdine."   
  [&  forms] 
  ` ( binding  [*out*  bit-bucket-writer] 
     ~@forms ))

( noprint 
 ( println  "Bonjour, personne!" ))

Dans cet exemple, dix threads manipulent une structure de données partagée, qui se compose de cent vecteurs contenant dix numéros uniques de début séquentiels. Chaque thread choisit deux positions aléatoires dans deux vecteurs aléatoires et les échange. Toutes les modifications apportées aux vecteurs sont effectuées dans les transactions à l'aide du système de mémoire transactionnelle du logiciel de Clojure . C'est pourquoi même après mille itérations, aucun numéro n'est perdu.

( defn  run  [nvecs  nitems  nthreads  niters] 
  ( let  [vec-refs  ( vec  ( map  ( comp  ref  vec ) 
                           ( partition  nitems  ( range  ( *  nvecs  nitems ))))) 
        swap  #( let  [v1  ( rand-int  nvecs ) 
                    v2  ( rand-int  nvecs ) 
                    i1  ( rand-int  nitems ) 
                    i2  ( rand-int  nitems ) ] 
                ( dosync 
                 ( let  [temp  ( nth  @ ( vec-refs  v1 )  i1 ) ] 
                   ( alter  ( vec-  refs v1 ) assoc  i1 ( nth @ ( vec-refs v2 ) i2 )) ( alter ( vec- refs v2 ) assoc i2 temp )))) report #( do ( prn ( map deref vec- refs )) ( println "Distinct:" ( count ( distinct ( apply concat ( map deref vec- refs )))))) ] ( report ) ( dorun ( apply pcalls ( repeat nthreads #( dotimes [ _niters] ( swap ))))) ( report )))     
                        
         
                    
                  
                                
    
            
    

( exécuter  100  10  10  100000 )

Sortie de l'exemple précédent :

( [0  1  2  3  4  5  6  7  8  9]  [10  11  12  13  14  15  16  17  18  19]  ... 
 [990  991  992  993  994  995  996  997  998  999] ) 
Distinct :  1000
 
( [382  318  466  963  619  22  21  273  45  596]  [808  639  804  471  394  904  952  75  289  778]  ... 
 [ 484  216  622  139  651  592  379  228  242  355 ] )
 

Bibliographie

Liens externes

Références

  1. ^ "Principes fondamentaux" . Rich Hickey (en anglais) . Récupéré le 17/10/2008 ceci n'a pas de paradigme .