Severity: Notice
Message: Undefined offset: 1
Filename: infosekolah/leftmenudasboard.php
Line Number: 33
Line Number: 34
.clj
.cljs
.cljc
.edn
.cljr
Clojure (вимовляється приблизно кложер, так само як англ. closure — Замикання) — сучасний діалект мови програмування Lisp. Це мова загального призначення, що підтримує інтерактивну розробку, зорієнтовану на функційне програмування, спрощує багатопотокове програмування, та містить риси сучасних скриптових мов.
Clojure працює на Java Virtual Machine і Common Language Runtime. Як і інші Lisp-подібні мови, Clojure розглядає код як дані і має потужну систему макросів.
Вихідний код компілятора Clojure, бібліотек і runtime-компонентів розповсюджується в рамках ліцензії Eclipse Public License.
Річард Гіккі розробив Clojure, оскільки йому був потрібен сучасний Lisp для функціонального програмування, розрахований на інтеграцію з розповсюдженою платформою Java й розроблений для паралельного програмування.[3][4]
Підхід Clojure до паралельності характеризується концепцією тотожностей,[5] що представляють серію незмінних станів протягом часу. Оскільки стани є незмінними значеннями, будь-яка кількість обробників може паралельно обробляти їх, і конкуренція зводиться до питання керування змінами від одного стану до іншого. З цією метою, Clojure надає декілька типів змінюваних посилань, кожен з яких має добре визначену семантику переходу між станами.
Як і інші Lisp-подібні мови, синтаксис Clojure побудовано на S-виразах (англ. S-expression), які в процесі синтаксичного розбору спершу перетворюються на структури даних за допомогою функції-читача (англ. reader), перш ніж компілюються. Clojure's reader підтримує літеральний синтаксис для хеш-таблиць, множин та векторів на додаток до списків, і вони передаються компілятору як є. Іншими словами, компілятор Clojure компілює не лише спискові структури даних, але й безпосередньо підтримує всі названі вище типи. Clojure — Lisp-1, і не є сумісним за кодом з іншими діалектами мови Lisp.
Система макросів Clojure дуже схожа на використовувану в Common Lisp, з тією відмінністю, що версія синтаксичного цитування Clojure (з використанням знаку `) доповнює символи їхніми просторами імен. Це допомагає запобігти ненавмисному перехопленню імен, оскільки прив'язка до імен, доповнених простором імен, заборонена. Є можливість форсувати таке захоплення імен, але це має бути зроблено явно. Clojure також не дозволяє переприв'язку глобальних імен з інших просторів імен, які були імпортовані в поточний простір.
Реалізації Clojure для відмінних від JVM платформ:
Hello world!:
(println "Привіт, світе!")
Hello World з графічним інтерфейсом користувача:
(javax.swing.JOptionPane/showMessageDialog nil "Привіт, світе!" )
Thread-безпечний генератор унікальних серійних номерів:
(let [i (atom 0)] (defn generate-unique-id "Повертає унікальний числовий ID при кожному виклику." [] (swap! i inc)))
Анонімний субклас java.io.Writer, що не пише нікуди, і макрос, що використовує це для відключення друку в своїх межах:
java.io.Writer
(def bit-bucket-writer (proxy [java.io.Writer] [] (write [buf] nil) (close [] nil) (flush [] nil))) (defmacro noprint "Обчислює задані вирази з відключеним друком в *out*." [& forms] `(binding [*out* bit-bucket-writer] ~@forms)) (noprint (println "Привіт, ніхто!"))
10 тредів, що маніпулюють однією спільною структурою даних, яка складається з 100 векторів, кожен з яких містить 10 (початково послідовних) унікальних чисел. Кожен тред багато разів обирає дві випадкові позиції у двох випадкових векторах і обмінює їх. Усі зміни векторів відбуваються в транзакціях шляхом використання системи програмної пам'яті транзакцій Clojure. Ось чому навіть після 100 000 ітерацій кожного треда жодне число не втрачено.
(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))) (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
Ханойська вежа. Функція, що генерує розв'язок задачі у вигляді лінивої послідовності, та форматований вивід результату:
(defn lazy-hanoi [n a b c] (lazy-seq (when-not (zero? n) (lazy-cat (lazy-hanoi (dec n) a c b) [[a b]] (lazy-hanoi (dec n) c b a))))) (defn print-hanoi [n a b c] (doseq [[from to] (lazy-hanoi n a b c)] (printf "%s -> %s;\t" from to)))
Макрос, що здійснює обмін двох глобальних змінних. При кожному виклику макроса замість temp# підставляється новий унікальний ідентифікатор.
(defmacro swap [a b] `(do (def temp# ~a) (def ~a ~b) (def ~b temp#)))
{{cite web}}
Портал «Програмування» Портал «Вільне програмне забезпечення»