Clojure - Clojure
| Paradigme | multi-paradigme : |
|---|---|
| Familie | Lisp |
| Designet af | Rich Hickey |
| Første gang dukkede op | 2007 |
| Stabil udgivelse | 1.10.3 / 4. marts 2021
|
| Skrive disciplin | |
| Platform | |
| Licens | Eclipse Public License |
| Filnavn udvidelser |
|
| Internet side | clojure |
| Påvirket af | |
| Påvirket | |
| |
Clojure ( / k l oʊ ʒ ər / , ligesom lukning ) er en dynamisk og funktionel dialekt af programmeringssproget Lisp på Java- platformen. Ligesom andre Lisp -dialekter behandler Clojure kode som data og har et Lisp -makrosystem . Den nuværende udviklingsproces er samfundsstyret , overvåget af Rich Hickey som dens velvillige diktator for livet (BDFL).
Clojure går ind for uforanderlighed og uforanderlige datastrukturer og opfordrer programmører til at være eksplicitte om styring af identitet og dens tilstande. Dette fokus på programmering med uforanderlige værdier og eksplicitte progression-of-time konstruktioner har til formål at lette udviklingen af mere robuste, især samtidige , programmer, der er enkle og hurtige. Selvom dets typesystem er helt dynamisk , har den seneste indsats også søgt implementering af et afhængigt typesystem .
Kommerciel støtte til Clojure leveres af firmaet Cognitect, der sponsorerer en reklamekonference.
Historie og udviklingsproces
Rich Hickey er skaberen af Clojure -sproget. Før Clojure udviklede han dotLisp, et lignende projekt baseret på .NET -platformen, og tre tidligere forsøg på at levere interoperabilitet mellem Lisp og Java : en Java -fremmedsprogsgrænseflade til Common Lisp (jfli), A Foreign Object Interface for Lisp (FOIL) og en Lisp-venlig grænseflade til Java Servlets (Lisplets).
Hickey brugte cirka 2½ år på at arbejde på Clojure, inden han offentliggjorde det, meget af den tid arbejdede udelukkende på Clojure uden ekstern finansiering. I slutningen af dette tidspunkt sendte Hickey en e -mail, der meddelte sproget til nogle venner i Common Lisp -fællesskabet.
Udviklingsprocessen er community-driven og administreres på Clojure JIRA- projektsiden. Generel udviklingsdiskussion finder sted hos Clojure Google Group. Alle kan indsende spørgsmål og ideer på ask.clojure.org, men for at bidrage med patches skal man underskrive Clojure Contributor -aftalen. JIRA -problemer behandles af et team af screenere, og endelig godkender Rich Hickey ændringerne.
Clojures navn er ifølge Hickey et ordspil om programmeringskonceptet " lukning ", der indeholder bogstaverne C, L og J for henholdsvis C# , Lisp og Java - tre sprog, der havde stor indflydelse på Clojures design.
Designfilosofi
Rich Hickey udviklede Clojure, fordi han ønskede en moderne Lisp til funktionel programmering , symbiotisk med den etablerede Java -platform og designet til samtidighed .
Clojures tilgang til staten er kendetegnet ved identitetsbegrebet, der repræsenteres som en række uforanderlige tilstande over tid. Da stater er uforanderlige værdier, kan et vilkårligt antal arbejdere operere dem parallelt, og samtidighed bliver et spørgsmål om at styre ændringer fra en stat til en anden. Til dette formål giver Clojure flere mutable referencetyper , der hver har veldefineret semantik for overgangen mellem stater.
Sprogoversigt
| Version | Udgivelses dato | Store funktioner/forbedringer |
|---|---|---|
| 16. oktober 2007 | Indledende offentliggørelse | |
| 1.0 | 4. maj 2009 | Første stabile udgivelse |
| 1.1 | 31. december 2009 | Futures |
| 1.2 | 19. august 2010 | Protokoller |
| 1.3 | 23. september 2011 | Forbedret primitiv støtte |
| 1.4 | 15. april 2012 | Læser bogstaver |
| 1.5 | 1. marts 2013 | Reduktorer |
| 1.5.1 | 10. marts 2013 | Rettelse af en hukommelseslækage |
| 1.6 | 25. marts 2014 | Java API, forbedrede hash -algoritmer |
| 1.7 | 30. juni 2015 | Transducere, læserbetingelser |
| 1.8 | 19. januar 2016 | Yderligere strengfunktioner, direkte forbindelse, socket -server |
| 1.9 | 8. december 2017 | Integration med spec, kommandolinjeværktøjer |
| 1.10 | 17. december 2018 | Forbedret fejlrapportering, Java -kompatibilitet |
| 1.10.1 | 6. juni 2019 | Arbejde omkring en Java -performance -regression og forbedre fejlrapportering fra clojure.main
|
| 1.10.2 | 26. januar 2021 | Forbedringer i Java -interoperabilitet/kompatibilitet og andre vigtige sprogrettelser |
| 1.10.3 | 4. marts 2021 | understøttelse af præpl. til læserbetingelser |
|
Nyeste version
|
||
Clojure kører på Java -platformen, og som et resultat kan den integreres med Java og understøtter fuldt ud at kalde Java -kode fra Clojure, og Clojure -kode kan også kaldes fra Java. Fællesskabet bruger værktøjer som Leiningen til projektautomatisering og understøtter Maven -integration. Leiningen håndterer projektpakkehåndtering og afhængigheder og konfigureres ved hjælp af Clojure -syntaks.
Som de fleste andre Lisps er Clojures syntaks bygget på S-udtryk , der først analyseres i datastrukturer af en læser, før de kompileres. Clojures læser understøtter bogstavelig syntaks for kort , sæt og vektorer ud over lister, og disse kompileres direkte til de nævnte strukturer. Clojure er en Lisp-1 og er ikke beregnet til at være kodekompatibel med andre Lisp-dialekter, da den bruger sit eget sæt datastrukturer, der er uforenelige med andre Lips.
Som en Lisp-dialekt understøtter Clojure funktioner som førsteklasses objekter , en læse-eval – udskriv loop (REPL) og et makro system. Clojures Lisp -makrosystem ligner meget det i Common Lisp med den undtagelse, at Clojures version af backcitatet (kaldet "syntaks -citat") kvalificerer symboler med deres navneområde . Dette hjælper med at forhindre utilsigtet navnefangst, da binding til navneområde-kvalificerede navne er forbudt. Det er muligt at tvinge en fangende makroudvidelse, men det skal gøres eksplicit. Clojure tillader ikke brugerdefinerede læsermakroer, men læseren understøtter en mere begrænset form for syntaktisk udvidelse. Clojure understøtter multimetoder og til grænseflade -lignende abstraktioner har et protokolbaseret polymorfisme og datatypesystem ved hjælp af poster , der giver højtydende og dynamisk polymorfisme designet til at undgå udtryksproblemet .
Clojure har støtte til dovne sekvenser og tilskynder til princippet om uforanderlighed og vedvarende datastrukturer . Som et funktionelt sprog lægges der vægt på rekursion og funktioner i højere orden i stedet for bivirkning-baseret looping. Automatisk haleopkaldsoptimering understøttes ikke, da JVM ikke understøtter det indbygget; det er muligt at gøre det eksplicit ved at bruge recursøgeordet. Til parallel og samtidig programmering leverer Clojure software transaktionshukommelse , et reaktivt agentsystem og kanalbaseret samtidig programmering.
Clojure 1.7 introducerede læserbetingelser ved at tillade indlejring af Clojure og ClojureScript -kode i det samme navneområde. Transducere blev tilføjet som en metode til sammensætning af transformationer. Transducere muliggør funktioner i højere orden, såsom kort og fold, for at generalisere over enhver kilde til inputdata. Selvom disse funktioner traditionelt fungerer på sekvenser , giver transducere dem mulighed for at arbejde på kanaler og lade brugeren definere deres egne modeller for transduktion.
Alternative platforme
Clojures primære platform er Java , men der findes andre målimplementeringer . Den mest bemærkelsesværdige af disse er ClojureScript, der kompileres til ECMAScript 3 og ClojureCLR, en fuld port på .NET -platformen, der er interoperabel med sit økosystem. En undersøgelse af Clojure -fællesskabet med 1.060 respondenter foretaget i 2013 viste, at 47% af respondenterne brugte både Clojure og ClojureScript, når de arbejdede med Clojure. I 2014 var dette antal steget til 55%, i 2015, baseret på 2.445 respondenter, til 66%. Populære ClojureScript-projekter omfatter implementeringer af React- biblioteket, såsom Reagent, re-frame, Rum og Om.
Andre implementeringer
Andre implementeringer af Clojure på forskellige platforme inkluderer:
- CljPerl, Clojure oven på Perl
- Clojerl, Clojure on BEAM , Erlang virtuelle maskine
- clojure-py, Clojure i ren Python
- Ferret, kompilerer til selvstændig C ++ 11, der kan køre på mikrokontrollere
- Joker, en tolk og linter skrevet i Go
- Las3r, en delmængde af Clojure, der kører på ActionScript Virtual Machine (Adobe Flash Player -platformen)
- Pixie, Clojure-inspireret Lisp-dialekt skrevet i RPython
- Rouge, Clojure oven på YARV i Ruby
Popularitet
Med fortsat interesse for funktionel programmering er Clojures vedtagelse af softwareudviklere, der bruger Java -platformen, fortsat stigende. Sproget er også blevet anbefalet af softwareudviklere som Brian Goetz, Eric Evans, James Gosling , Paul Graham og Robert C. Martin . Mens ThoughtWorks vurderede funktionelle programmeringssprog for deres Technology Radar, beskrev Clojure som "en enkel, elegant implementering af Lisp på JVM" i 2010 og promoverede dens status til "ADOPT" i 2012.
I "JVM Ecosystem Report 2018" (der blev påstået at være "den største undersøgelse nogensinde af Java -udviklere"), blev Clojure udarbejdet i samarbejde af Snyk og Java Magazine, som det 2. mest anvendte programmeringssprog på JVM for " hovedapplikationer ". Clojure bruges i industrien af virksomheder som Apple , Atlassian , Funding Circle , Netflix , Puppet og Walmart samt offentlige instanser som NASA . Det er også blevet brugt til kreativ computing, herunder billedkunst, musik, spil og poesi.
Værktøjer
Værktøjer til Clojure -udvikling har oplevet betydelige forbedringer gennem årene. Følgende er en liste over nogle populære IDE'er og tekstredigerere med plug-ins, der tilføjer understøttelse af programmering i Clojure:
- Atom , med klor
- Emacs , med CIDER
- IntelliJ IDEA , med Clojure-Kit eller Cursive (en gratis licens er tilgængelig til ikke-kommerciel brug)
- Lysbord
- Vim , med pejs. Vim , vim-iset eller trylle (kun Neovim)
- Visual Studio Code , med Calva eller Clover
Ud over de værktøjer, som fællesskabet leverer, er de officielle Clojure CLI -værktøjer også blevet tilgængelige på Linux , macOS og Windows siden Clojure 1.9.
Funktioner efter eksempel
Følgende eksempler kan køres i en Clojure REPL, f.eks. Én, der startede med Clojure CLI -værktøjerne eller en online REPL, f.eks. En, der er tilgængelig på REPL.it.
Enkelhed
På grund af den stærke vægt på enkelhed består typiske Clojure -programmer for det meste af funktioner og enkle datastrukturer (dvs. lister, vektorer, kort og sæt):
;; A typical entry point of a Clojure program:
;; `-main` function
(defn -main ; name
[& args] ; (variable) parameters
(println "Hello, World!")) ; body
Programmering hos REPL
Ligesom andre Lips er en af de ikoniske egenskaber ved Clojure interaktiv programmering på REPL . Bemærk, at i de følgende eksempler ;starter en linjekommentar og ;; =>angiver det forventede output:
; define a var
(def a 42)
;; => #'user/a
; call a function named `+`
(+ a 8)
;; => 50
; call a function named `even?`
(even? a)
;; => true
; define a function that returns the remainder of `n` when divided by 10
(defn foo [n] (rem n 10))
;; => #'user/foo
; call the function
(foo a)
;; => 2
; print the docstring of `rem`
(doc rem)
;; =>
-------------------------
clojure.core/rem
([num div])
remainder of dividing numerator by denominator.
; print the source of `rem`
(source rem)
;; =>
(defn rem
"remainder of dividing numerator by denominator."
{:added "1.0"
:static true
:inline (fn [x y] `(. clojure.lang.Numbers (remainder ~x ~y)))}
[num div]
(. clojure.lang.Numbers (remainder num div)))
Navne ved runtime
I modsætning til andre runtime -miljøer, hvor navne samles væk, er Clojures runtime -miljø let introspectable ved hjælp af normale Clojure -datastrukturer:
; define a var
(def a 42)
;; => #'user/a
; get a map of all public vars interned in the `user` namespace
(ns-publics 'user)
;; => {a #'user/a}
; reference the var via `#'` (reader macro) and
; its associated, namespace-qualified symbol `user/a`
#'user/a
;; => #'user/a
; de-reference (get the value of) the var
(deref #'user/a)
;; => 42
; define a function (with a docstring) that
; returns the remainder of `n` when divided by 10
(defn foo "returns `(rem n 10)`" [n] (rem n 10))
;; => #'user/foo
; get the metadata of the var `#'user/foo`
(meta #'user/foo)
;; =>
{:arglists ([n]),
:doc "returns `(rem n 10)`",
:line 1,
:column 1,
:file "user.clj",
:name foo,
:ns #namespace[user]}
Kode som data (homoiconicity)
Ligner andre Lisps , Clojure er homoiconic (også kendt som "kode som data"). I eksemplet herunder kan vi se, hvordan man skriver kode, der ændrer selve koden:
; call a function (code)
(+ 1 1)
;; => 2
; quote the function call
; (turning code into data, which is a list of symbols)
(quote (+ 1 1))
;; => (+ 1 1)
; get the first element on the list
; (operating on code as data)
(first (quote (+ 1 1)))
;; => +
; get the last element on the list
; (operating on code as data)
(last (quote (+ 1 1)))
;; => 1
; get a new list by replacing the symbols on the original list
; (manipulating code as data)
(map (fn [form]
(case form
1 'one
+ 'plus))
(quote (+ 1 1)))
;; => (plus one one)
Ekspressive operatører til datatransformation
Gevindet makroer ( ->, ->>, og venner) kan syntaktisk udtrykke indvinding af rygende en indsamling af data gennem en række transformationer:
(->> (range 10)
(map inc)
(filter even?))
;; => (2 4 6 8 10)
Dette kan også opnås mere effektivt ved hjælp af transducere:
(sequence (comp (map inc)
(filter even?))
(range 10))
;; => (2 4 6 8 10)
Trådsikker styring af identitet og stat
En trådsikker generator med unikke serienumre (men ligesom mange andre Lisp-dialekter har Clojure en indbygget gensymfunktion, som den bruger internt):
(def i (atom 0))
(defn generate-unique-id
"Returns a distinct numeric ID for each call."
[]
(swap! i inc))
Makroer
En anonym underklasse af java.io.Writerdet skriver ikke til noget, og en makro, der bruger det til at dæmpe alle udskrifter i det:
(def bit-bucket-writer
(proxy [java.io.Writer] []
(write [buf] nil)
(close [] nil)
(flush [] nil)))
(defmacro noprint
"Evaluates the given `forms` with all printing to `*out*` silenced."
[& forms]
`(binding [*out* bit-bucket-writer]
~@forms))
(noprint
(println "Hello, nobody!"))
;; => nil
Sproginteroperabilitet med Java
Clojure blev skabt fra bunden for at omfavne sine værtsplatforme som et af dets designmål og giver dermed fremragende sproginteroperabilitet med Java:
; call an instance method
(.toUpperCase "apple")
;; => "APPLE"
; call a static method
(System/getProperty "java.vm.version")
;; => "12+33"
; create an instance of `java.util.HashMap` and
; add some entries
(doto (java.util.HashMap.)
(.put "apple" 1)
(.put "banana" 2))
;; => {"banana" 2, "apple" 1}
; create an instance of `java.util.ArrayList` and
; increment its elements with `clojure.core/map`
(def al (doto (java.util.ArrayList.)
(.add 1)
(.add 2)
(.add 3)))
(map inc al)
;; => (2 3 4)
; show a message dialog using Java Swing
(javax.swing.JOptionPane/showMessageDialog
nil
"Hello, World!")
;; => nil
Software transaktionshukommelse
10 tråde, der manipulerer en delt datastruktur, som består af 100 vektorer, der hver indeholder 10 (oprindeligt sekventielle) unikke tal. Hver tråd vælger derefter gentagne gange to tilfældige positioner i to tilfældige vektorer og bytter dem. Alle ændringer af vektorerne sker i transaktioner ved at bruge Clojures software transaktionshukommelsessystem :
(defn run
[nvecs nitems nthreads niters]
(let [vec-refs
(->> (* nvecs nitems)
(range)
(into [] (comp (partition-all nitems)
(map vec)
(map ref))))
swap
#(let [v1 (rand-int nvecs)
v2 (rand-int nvecs)
i1 (rand-int nitems)
i2 (rand-int nitems)]
(dosync
(let [tmp (nth @(vec-refs v1) i1)]
(alter (vec-refs v1) assoc i1 (nth @(vec-refs v2) i2))
(alter (vec-refs v2) assoc i2 tmp))))
report
#(->> vec-refs
(into [] (comp (map deref)
(map (fn [v] (prn v) v))
cat
(distinct)))
(count)
(println "Distinct:"))]
(report)
(->> #(dotimes [_ niters] (swap))
(repeat nthreads)
(apply pcalls)
(dorun))
(report)))
(run 100 10 10 100000)
;; =>
[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]
Distinct: 1000
nil
Se også
Referencer
Yderligere læsning
- Sotnikov, Dmitri (2020), Webudvikling med Clojure (3. udgave), Pragmatisk bogreol , ISBN 978-1-68050-682-2
- Olsen, Russ (2018), Getting Clojure , Pragmatisk reol , ISBN 978-1-68050-300-5
- Miller, Alex; Halloway, Stuart; Bedra, Aaron (2018), Programming Clojure (3. udgave), Pragmatisk bogreol , ISBN 978-1-68050-246-6
- Rathore, Amit; Avila, Francis (2015), Clojure in Action (2. udgave), Manning , ISBN 978-1-61729-152-4
- Higginbotham, Daniel (2015), Clojure for the Brave and True , No Starch Press , ISBN 978-1-59327-591-4
- Gamble, Julian (2015), Clojure Recipes , Pearson Publishing , ISBN 978-0-32192-773-6
- Vandgrift, Ben; Miller, Alex (2015), Clojure Applied , Pragmatic Bookshelf , ISBN 978-1-68050-074-5
- Rochester, Eric (2015), Clojure Data Analysis Cookbook (2. udgave), Packt Publishing , ISBN 978-1-78439-029-7
- Fogus, Michael; Houser, Chris (2014), The Joy of Clojure (2. udgave), Manning , ISBN 978-1-617291-41-8
- Kelker, Ryan (2013), Clojure for Domain-specific Languages , Packt Publishing , ISBN 978-1-78216-650-4
- Rochester, Eric (2014), Mastering Clojure Data Analysis , Packt Publishing , ISBN 978-1-78328-413-9
- Emerick, Chas; Carper, Brian; Grand, Christophe (19. april 2012), Clojure Programming , O'Reilly Media , ISBN 978-1-4493-9470-7
- VanderHart, Luke; Sierra, Stuart (7. juni 2010), Practical Clojure , Apress , ISBN 978-1-4302-7231-1
eksterne links
| 1955 | 1960 | 1965 | 1970 | 1975 | 1980 | 1985 | 1990 | 1995 | 2000 | 2005 | 2010 | 2015 | 2020 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| LISP 1, 1.5, LISP 2 (opgivet) | ||||||||||||||
| Maclisp | ||||||||||||||
| Interlisp | ||||||||||||||
| MDL (programmeringssprog) | ||||||||||||||
| Lisp Machine Lisp | ||||||||||||||
| Skema | R5RS | R6RS | R7RS lille | |||||||||||
| NIL | ||||||||||||||
| ZIL (Zork Implementation Language) | ||||||||||||||
| Franz Lisp | ||||||||||||||
| Almindelig Lisp | ||||||||||||||
| Le Lisp | ||||||||||||||
| T | ||||||||||||||
| Chez -ordning | ||||||||||||||
| Emacs Lisp | ||||||||||||||
| AutoLISP | ||||||||||||||
| PicoLisp | ||||||||||||||
| EuLisp | ||||||||||||||
| ISLISP | ||||||||||||||
| OpenLisp | ||||||||||||||
| PLT -ordning | Ketcher | |||||||||||||
| GNU Guile | ||||||||||||||
| Visuel LISP | ||||||||||||||
| Clojure | ||||||||||||||
| Bue | ||||||||||||||
| LFE | ||||||||||||||
| Hy | ||||||||||||||