Учебники

Clojure — Краткое руководство

Clojure — Обзор

Clojure — это динамический функциональный язык программирования высокого уровня. Clojure разработан на основе языка программирования LISP и имеет компиляторы, которые позволяют ему работать как в среде выполнения Java, так и в среде .Net.

Прежде чем говорить о Clojure, давайте кратко опишем язык программирования LISP. LISP имеют крошечное языковое ядро, почти не имеют синтаксиса и мощные средства макросов. С помощью этих функций вы можете согнуть LISP, чтобы он соответствовал вашему дизайну, а не наоборот. LISP был там в течение долгого времени, начиная с 1958 года.

Обычный LISP читает в выражении, оценивает его, а затем распечатывает результат. Например, если вы хотите вычислить значение простого математического выражения 4 + 6, введите.

USER(1) (+ 4 6)

Clojure имеет следующие ключевые цели высокого уровня в качестве языка программирования.

  • Он основан на языке программирования LISP, который делает свои выражения кода меньше, чем традиционные языки программирования.

  • Это функциональный язык программирования.

  • Основное внимание уделяется неизменности, которая в основном заключается в том, что вам не следует вносить какие-либо изменения в объекты, созданные на месте.

  • Он может управлять состоянием приложения для программиста.

  • Поддерживает параллелизм.

  • Он охватывает существующие языки программирования. Например, Clojure может использовать всю экосистему Java для управления выполнением кода через JVM.

Он основан на языке программирования LISP, который делает свои выражения кода меньше, чем традиционные языки программирования.

Это функциональный язык программирования.

Основное внимание уделяется неизменности, которая в основном заключается в том, что вам не следует вносить какие-либо изменения в объекты, созданные на месте.

Он может управлять состоянием приложения для программиста.

Поддерживает параллелизм.

Он охватывает существующие языки программирования. Например, Clojure может использовать всю экосистему Java для управления выполнением кода через JVM.

Официальный сайт Clojure — https://clojure.org/

Обзор Clojure

Clojure — Окружающая среда

Существует множество способов работы с Clojure в качестве языка программирования. Мы рассмотрим два способа работы с программированием Clojure.

  • Leiningen — Leiningen является важным инструментом для создания, создания и автоматизации проектов Clojure.

  • Eclipse Plugin — есть плагин CounterClockwise, который доступен для Eclipse для выполнения разработки Clojure в Eclipse IDE.

Leiningen — Leiningen является важным инструментом для создания, создания и автоматизации проектов Clojure.

Eclipse Plugin — есть плагин CounterClockwise, который доступен для Eclipse для выполнения разработки Clojure в Eclipse IDE.

Leiningen Установка

Перед продолжением установки убедитесь, что выполнены следующие системные требования.

Системные Требования

JDK JDK 1,7 или выше
объем памяти 2 ГБ ОЗУ (рекомендуется)

Шаг 1 — Загрузите двоичную установку. Перейдите по ссылке http: // leiningen-wininstaller, чтобы получить установщик Windows. Нажмите на опцию, чтобы начать загрузку установщика Groovy.

Шаг 2 — Запустите установщик и нажмите кнопку «Далее».

Запуск установщика

Шаг 3 — Укажите местоположение для установки и нажмите кнопку «Далее».

Место установки

Шаг 4 — Программа установки обнаружит местоположение существующей установки Java. Нажмите кнопку Далее, чтобы продолжить.

Установка Java

Шаг 5 — Нажмите кнопку Установить, чтобы начать установку.

Начать установку

После завершения установки вам будет предложено открыть REPL Clojure, который может использоваться для создания и тестирования ваших программ Clojure.

Программы Clojure

Установка Затмения

Перед продолжением установки убедитесь, что выполнены следующие системные требования.

Системные Требования

JDK JDK 1,7 или выше
Затмение Затмение 4.5 (Марс)

Шаг 1 — Откройте Eclipse и щелкните пункт меню. Нажмите Справка → Eclipse Marketplace.

Eclipse Marketplace

Шаг 2 — Введите ключевое слово Clojure в появившемся диалоговом окне и нажмите кнопку «Перейти». Опция для против часовой стрелки появится, нажмите кнопку Установить, чтобы начать установку этого плагина.

Диалоговое окно Clojure

Шаг 3 — В следующем диалоговом окне нажмите кнопку «Подтвердить», чтобы начать установку.

Кнопка подтверждения закрытия

Шаг 4 — В следующем диалоговом окне вам будет предложено принять лицензионное соглашение. Примите лицензионное соглашение и нажмите кнопку Готово, чтобы продолжить установку.

Принять лицензионное соглашение

Начнется установка, и после ее завершения вам будет предложено перезапустить Eclipse.

После перезапуска Eclipse вы увидите в Eclipse возможность создать новый проект Clojure.

Закрытый проект

Clojure — основной синтаксис

Чтобы понять основной синтаксис Clojure, давайте сначала рассмотрим простую программу Hello World.

Hello World как полная программа

Напишите «Hello world» в полной программе Clojure. Ниже приведен пример.

пример

Live Demo

(ns clojure.examples.hello
   (:gen-class))
(defn hello-world []
   (println "Hello World"))
(hello-world)

Следующие вещи необходимо отметить о вышеупомянутой программе.

  • Программа будет написана в файле с именем main.clj. Расширение «clj» — это расширение имени файла кода clojure. В приведенном выше примере имя файла называется main.clj.

  • Ключевое слово defn используется для определения функции. Мы подробно рассмотрим функции в другой главе. Но пока знайте, что мы создаем функцию с именем helloworld, которая будет иметь наш основной код Clojure.

  • В нашем коде Clojure мы используем оператор println для вывода «Hello World» на вывод консоли.

  • Затем мы вызываем функцию hello-world, которая, в свою очередь, запускает оператор println.

Программа будет написана в файле с именем main.clj. Расширение «clj» — это расширение имени файла кода clojure. В приведенном выше примере имя файла называется main.clj.

Ключевое слово defn используется для определения функции. Мы подробно рассмотрим функции в другой главе. Но пока знайте, что мы создаем функцию с именем helloworld, которая будет иметь наш основной код Clojure.

В нашем коде Clojure мы используем оператор println для вывода «Hello World» на вывод консоли.

Затем мы вызываем функцию hello-world, которая, в свою очередь, запускает оператор println.

Вышеуказанная программа производит следующий вывод.

Выход

Hello World

Общая форма заявления

Общая форма любого оператора должна оцениваться в фигурных скобках, как показано в следующем примере.

(+ 1 2)

В приведенном выше примере все выражение заключено в фигурные скобки. Результат вышеприведенного оператора равен 3. Оператор + действует как функция в Clojure, которая используется для добавления чисел. Значения 1 и 2 известны как параметры функции .

Давайте рассмотрим другой пример. В этом примере str — это оператор, который используется для объединения двух строк. Строки «Hello» и «World» используются в качестве параметров.

(str "Hello" "World")

пример

Если мы объединим два приведенных выше утверждения и напишем программу, это будет выглядеть следующим образом.

Live Demo

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (println (str "Hello World"))
   (println (+ 1 2)))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

Hello World
3

Пространства имен

Пространство имен используется для определения логической границы между модулями, определенными в Clojure.

Текущее пространство имен

Это определяет текущее пространство имен, в котором находится текущий код Clojure.

Синтаксис

*ns*

пример

В командном окне REPL выполните следующую команду.

*ns*

Выход

Когда мы запустим указанную выше команду, вывод будет отложен в зависимости от текущего пространства имен. Ниже приведен пример вывода. Пространство имен кода Clojure —

clojure.examples.hello

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (println (str "Hello World"))
   (println (+ 1 2)))
(Example)

Требовать заявление в Clojure

Код Clojure упакован в библиотеках. Каждая библиотека Clojure принадлежит пространству имен, которое аналогично пакету Java. Вы можете загрузить библиотеку Clojure с помощью оператора Require.

Синтаксис

(require quoted-namespace-symbol)

пример

Ниже приведен пример использования этого утверждения.

(ns clojure.examples.hello
   (:gen-class))
(require clojure.java.io’)
(defn Example []
   (.exists (file "Example.txt")))
(Example)

В приведенном выше коде мы используем ключевое слово require для импорта пространства имен clojure.java.io, в котором есть все функции, необходимые для ввода / вывода. Поскольку у нас нет необходимой библиотеки, мы можем использовать функцию ‘file’ в приведенном выше коде.

Комментарии в Clojure

Комментарии используются для документирования вашего кода. Однострочные комментарии идентифицируются с помощью ;; в любой позиции на линии. Ниже приведен пример.

пример

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println "Hello World"))
(Example)

Разделители

В Clojure операторы могут быть разделены или разделены с помощью фигурных или квадратных скобок.

пример

Ниже приведены два примера.

Live Demo

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println (+ 1 2 3)))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

6

пример

Ниже приведен еще один пример.

Live Demo

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println [+ 1 2 3]))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

[#object[clojure.core$_PLUS_ 0x10f163b "clojure.core$_PLUS_@10f163b"] 1 2 3]

Пробелы

Пробелы могут использоваться в Clojure для разделения различных компонентов оператора для большей ясности. Это можно сделать с помощью оператора запятой (,).

Например, следующие два оператора эквивалентны, и результат обоих операторов будет 15.

(+ 1 2 3 4 5)
(+ 1, 2, 3, 4, 5)

Хотя Clojure игнорирует запятые, он иногда использует их, чтобы программисту было легче читать.

Например, если у вас есть хеш-карта, подобная следующей (def a-map {: a 1: b 2: c 3}), и вы запросите ее значение в окне REPL, Clojure напечатает вывод как {: a 1, : b 2,: c 3}.

Результаты легче читать, особенно если вы смотрите на большой объем данных.

Символы

В Clojure символы эквивалентны идентификаторам в других языках программирования. Но в отличие от других языков программирования, компилятор видит символы как фактические строковые значения. Поскольку символ является значением, символ может быть сохранен в коллекции, передан в качестве аргумента функции и т. Д., Как и любой другой объект.

Символ может содержать только буквенно-цифровые символы и ‘* +! /. : — _? ‘ но не должен начинаться с цифры или двоеточия.

Ниже приведены действительные примеры символов.

tutorial-point!
TUTORIAL
+tutorial+

Структура проекта Clojure

Наконец, давайте поговорим о типичной структуре проекта для проекта Clojure. Поскольку код Clojure выполняется на виртуальной машине Java, большая часть структуры проекта в Clojure аналогична той, что вы найдете в проекте Java. Ниже приведен снимок примера структуры проекта в Eclipse для проекта Clojure.

Основной синтаксис

Следующие ключевые вещи должны быть отмечены о вышеупомянутой структуре программы.

  • demo_1 — это пакет, в котором находится файл кода Clojure.

  • core.clj — это основной файл кода Clojure, который будет содержать код для приложения Clojure.

  • Папка Leiningen содержит файлы, такие как clojure-1.6.0.jar, которые необходимы для запуска любого приложения на основе Clojure.

  • Файл pom.properties будет содержать такую ​​информацию, как groupId, artifactId и версия проекта Clojure.

  • Файл project.clj содержит информацию о самом приложении Clojure. Ниже приведен пример содержимого файла проекта.

demo_1 — это пакет, в котором находится файл кода Clojure.

core.clj — это основной файл кода Clojure, который будет содержать код для приложения Clojure.

Папка Leiningen содержит файлы, такие как clojure-1.6.0.jar, которые необходимы для запуска любого приложения на основе Clojure.

Файл pom.properties будет содержать такую ​​информацию, как groupId, artifactId и версия проекта Clojure.

Файл project.clj содержит информацию о самом приложении Clojure. Ниже приведен пример содержимого файла проекта.

(defproject demo-1 "0.1.0-SNAPSHOT"
   :description "FIXME: write description"
   :url "http://example.com/FIXME"
   :license {
      :name "Eclipse Public License"
      :url "http://www.eclipse.org/legal/epl-v10.html"
   }
   :dependencies [[org.clojure/clojure "1.6.0"]])

Clojure — REPL

REPL (цикл чтения-проверки-печати) — это инструмент для экспериментов с кодом Clojure. Это позволяет вам взаимодействовать с работающей программой и быстро попробовать, если все работает так, как должно. Это делается путем предоставления вам приглашения, где вы можете ввести код. Затем он читает ваш ввод, оценивает его, печатает результат и зацикливается, снова предлагая вам приглашение.

Этот процесс обеспечивает быстрый цикл обратной связи, который невозможен в большинстве других языков.

Начало сессии REPL

Сеанс REPL можно запустить в Лейнингене, введя следующую команду в командной строке.

lein repl

Это запустит следующее окно REPL.

Окно REPL

Затем вы начинаете оценивать команды Clojure в окне REPL по мере необходимости.

Чтобы начать сеанс REPL в Eclipse, щелкните пункт «Меню», выберите «Запуск от имени» → «Clojure Application».

REPL сессия

Это запустит новый сеанс REPL в отдельном окне вместе с выводом на консоль.

REPL Консольный выход

Концептуально, REPL похож на Secure Shell (SSH). Аналогично тому, как вы можете использовать SSH для взаимодействия с удаленным сервером, Clojure REPL позволяет вам взаимодействовать с запущенным процессом Clojure. Эта функция может быть очень мощной, потому что вы даже можете прикрепить REPL к живому производственному приложению и изменять свою программу во время ее работы.

Специальные переменные в REPL

REPL включает в себя некоторые полезные переменные, широко используемой является специальная переменная * 1, * 2 и * 3. Они используются для оценки результатов трех самых последних выражений.

В следующем примере показано, как можно использовать эти переменные.

user => "Hello"
Hello
user => "World"
World
user => (str *2 *1)
HelloWorld

В приведенном выше примере первые две строки отправляются в окно вывода REPL как «Hello» и «World» соответственно. Затем переменные * 2 и * 1 используются для вызова последних 2 оцененных выражений.

Clojure — Типы данных

Clojure предлагает широкий спектр встроенных типов данных.

Встроенные типы данных

Ниже приведен список типов данных, которые определены в Clojure.

  • Целые числа. Ниже представлены целые числа, доступные в Clojure.

    • Десятичные целые числа (Short, Long и Int) — используются для представления целых чисел. Например, 1234.

    • Восьмеричные числа — Они используются для представления чисел в восьмеричном представлении. Например, 012.

    • Шестнадцатеричные числа — они используются для представления чисел в представлении. Например, 0xff.

    • Корневые числа — Они используются для представления чисел в радикальном представлении. Например, 2r1111, где основанием является целое число от 2 до 36 включительно.

Целые числа. Ниже представлены целые числа, доступные в Clojure.

Десятичные целые числа (Short, Long и Int) — используются для представления целых чисел. Например, 1234.

Восьмеричные числа — Они используются для представления чисел в восьмеричном представлении. Например, 012.

Шестнадцатеричные числа — они используются для представления чисел в представлении. Например, 0xff.

Корневые числа — Они используются для представления чисел в радикальном представлении. Например, 2r1111, где основанием является целое число от 2 до 36 включительно.

  • Плавающая запятая

    • Значение по умолчанию используется для представления 32-битных чисел с плавающей запятой. Например, 12.34.

    • Другое представление — научная запись. Например, 1.35e-12.

Плавающая запятая

Значение по умолчанию используется для представления 32-битных чисел с плавающей запятой. Например, 12.34.

Другое представление — научная запись. Например, 1.35e-12.

  • char — определяет односимвольный литерал Символы определяются с помощью символа обратной реакции. Например, / е.

  • Boolean — Представляет логическое значение, которое может быть как true, так и false.

  • Строка — это текстовые литералы, которые представлены в виде цепочки символов. Например, «Привет, мир».

  • Nil — используется для представления значения NULL в Clojure.

  • Atom — Atoms предоставляют способ управления общим, синхронным, независимым состоянием. Они являются ссылочными типами, такими как refs и vars.

char — определяет односимвольный литерал Символы определяются с помощью символа обратной реакции. Например, / е.

Boolean — Представляет логическое значение, которое может быть как true, так и false.

Строка — это текстовые литералы, которые представлены в виде цепочки символов. Например, «Привет, мир».

Nil — используется для представления значения NULL в Clojure.

Atom — Atoms предоставляют способ управления общим, синхронным, независимым состоянием. Они являются ссылочными типами, такими как refs и vars.

Связанные значения

Поскольку все типы данных в Clojure наследуются от Java, ограниченные значения такие же, как в языке программирования Java. В следующей таблице приведены максимально допустимые значения для числовых и десятичных литералов.

литералы Изменяется
короткий От -32 768 до 32 767
ИНТ От -2 147 483 648 до 2 147 483 647
долго От -9,223,372,036,854,775,808 до +9,223,372,036,854,775,807
поплавок От 1.40129846432481707e-45 до 3.40282346638528860e + 38
двойной 4.94065645841246544e-324d до 1.79769313486231570e + 308d

Числовые типы классов

В дополнение к примитивным типам допускаются следующие типы объектов (иногда называемые типами-обертками).

название
java.lang.Byte
java.lang.Short
java.lang.Integer
java.lang.Long
java.lang.Float
java.lang.Double

пример

Следующая программа показывает консолидированный код clojure для демонстрации типов данных в Clojure.

Live Demo

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a integer variable
   (def x 1)
   
   ;; The below code declares a float variable
   (def y 1.25)
   
   ;; The below code declares a string variable
   (def str1 "Hello")
   (println x)
   (println y)
   (println str1))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

1
1.25
Hello

Clojure — переменные

В Clojure переменные определяются ключевым словом def . Это немного отличается, когда понятие переменных больше связано с привязкой. В Clojure значение связано с переменной. В Clojure следует отметить одну ключевую вещь: переменные являются неизменяемыми, что означает, что для изменения значения переменной ее необходимо уничтожить и заново создать.

Ниже приведены основные типы переменных в Clojure.

  • короткий — используется для представления короткого номера. Например, 10.

  • int — Используется для представления целых чисел. Например, 1234.

  • long — используется для представления длинного числа. Например, 10000090.

  • float — используется для представления 32-битных чисел с плавающей точкой. Например, 12.34.

  • char — определяет односимвольный литерал Например, «/ а».

  • Boolean — Представляет логическое значение, которое может быть как true, так и false.

  • Строка — это текстовые литералы, которые представлены в виде цепочки символов. Например, «Привет, мир».

короткий — используется для представления короткого номера. Например, 10.

int — Используется для представления целых чисел. Например, 1234.

long — используется для представления длинного числа. Например, 10000090.

float — используется для представления 32-битных чисел с плавающей точкой. Например, 12.34.

char — определяет односимвольный литерал Например, «/ а».

Boolean — Представляет логическое значение, которое может быть как true, так и false.

Строка — это текстовые литералы, которые представлены в виде цепочки символов. Например, «Привет, мир».

Объявления переменных

Ниже приводится общий синтаксис определения переменной.

Синтаксис

(def var-name var-value)

Где «var-name» — это имя переменной, а «var-value» — это значение, связанное с переменной.

пример

Ниже приведен пример объявления переменной.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a integer variable
   (def x 1)
   
   ;; The below code declares a float variable
   (def y 1.25)

   ;; The below code declares a string variable
   (def str1 "Hello")
   
   ;; The below code declares a boolean variable
   (def status true))
(Example)

Именование переменных

Имя переменной может состоять из букв, цифр и символа подчеркивания. Он должен начинаться либо с буквы, либо с подчеркивания. Прописные и строчные буквы различны, потому что Clojure, как и Java, чувствителен к регистру языков программирования.

пример

Ниже приведены некоторые примеры именования переменных в Clojure.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a Boolean variable with the name of status
   (def status true)
   
   ;; The below code declares a Boolean variable with the name of STATUS
   (def STATUS false)
   
   ;; The below code declares a variable with an underscore character.
   (def _num1 2))
(Example)

Примечание. В приведенных выше инструкциях из-за чувствительности к регистру в Clojure определены две различные переменные: status и STATUS.

В приведенном выше примере показано, как определить переменную с символом подчеркивания.

Переменные печати

Поскольку Clojure использует среду JVM, вы также можете использовать функцию println. Следующий пример показывает, как этого можно достичь.

пример

Live Demo

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   ;; The below code declares a integer variable
   (def x 1)
   
   ;; The below code declares a float variable
   (def y 1.25)
   
   ;; The below code declares a string variable
   (def str1 "Hello")
   (println x)
   (println y)
   (println str1))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

1
1.25
Hello

Clojure — Операторы

Оператор — это символ, который указывает компилятору выполнять определенные математические или логические манипуляции.

Clojure имеет следующие типы операторов —

  • Арифметические операторы
  • Реляционные операторы
  • Логические операторы
  • Битовые операторы

Примечание. В Clojure операторы и операнды работают следующим образом.

Синтаксис

(operator operand1 operand2 operandn)

Например,

пример

(+ 1 2)

Приведенный выше пример выполняет арифметическую операцию над числами 1 и 2.

Арифметические Операторы

Язык Clojure поддерживает обычные арифметические операторы как любой язык. Ниже приведены арифметические операторы, доступные в Clojure.

Показать примеры

оператор Описание пример
+ Добавление двух операндов (+1 1) даст 3
Вычитает второй операнд из первого (- 2 1) даст 1
* Умножение обоих операндов (* 2 2) даст 4
/ Деление числителя по знаменателю (float (/ 3 2)) даст 1,5
вкл Инкрементные операторы, используемые для увеличения значения операнда на 1 инк 5 даст 6
декабрь Инкрементные операторы, используемые для уменьшения значения операнда на 1 5 декабря даст 4
Максимум Возвращает самый большой из его аргументов макс 1 2 3 вернется 3
мин Возвращает наименьший из своих аргументов мин 1 2 3 вернется 1
рем Остаток от деления первого числа на второе rem 3 2 даст 1

Операторы отношений

Реляционные операторы позволяют сравнивать объекты. Ниже приведены реляционные операторы, доступные в Clojure.

Показать примеры

оператор Описание пример
знак равно Проверяет равенство между двумя объектами (= 2 2) даст истинное
не = Проверяет разницу между двумя объектами (не = 3 2) даст истинное
< Проверяет, является ли левый объект меньше правого операнда (<2 3) даст истинное
<= Проверяет, является ли левый объект меньше или равен правому операнду (<= 2 3) даст истинное
> Проверяет, является ли левый объект больше правого операнда (> 3 2) даст истинное
> = Проверяет, является ли левый объект больше или равен правому операнду (> = 3 2) даст истинное

Логические Операторы

Логические операторы используются для оценки булевых выражений. Ниже приведены логические операторы, доступные в Groovy.

Показать примеры

оператор Описание пример
а также Это логический оператор «и» (или правда правда) даст правда
или же Это логический оператор «или» (и правда ложь) даст ложь
не Это логический оператор «не» (не ложь) даст правду

Следующий фрагмент кода показывает, как могут использоваться различные операторы.

Битовые операторы

Clojure предоставляет четыре побитовых оператора. Ниже приведены побитовые операторы, доступные в Clojure.

Показать примеры

Sr.No. Оператор и описание
1

бит и

Это побитовый оператор «и»

2

бит или

Это побитовый оператор «или»

3

бит исключающее

Это побитовый «xor» или «Эксклюзивный» или «оператор»

4

бит не

Это побитовый оператор отрицания

бит и

Это побитовый оператор «и»

бит или

Это побитовый оператор «или»

бит исключающее

Это побитовый «xor» или «Эксклюзивный» или «оператор»

бит не

Это побитовый оператор отрицания

Ниже приведена таблица истинности, демонстрирующая этих операторов.

п Q р & д р | Q р ^ д
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Приоритет оператора

Как и в случае с LISP в целом, нет необходимости беспокоиться о приоритете операторов. Это одно из преимуществ S-выражений и префиксной нотации. Все функции оцениваются слева направо и наизнанку. Операторы в Clojure — это просто функции, и все полностью заключено в скобки.

Clojure — Петли

До сих пор мы видели операторы, которые выполняются одно за другим последовательно. Кроме того, в Clojure предоставляются операторы для изменения потока управления в логике программы. Затем они классифицируются в поток контрольных операторов, которые мы рассмотрим подробно.

Sr.No. Петли и описание
1 В то время как заявление

Оператор while выполняется сначала путем вычисления выражения условия (логическое значение), и, если результат равен true, тогда выполняются операторы цикла while.

2 Doseq Заявление

Утверждение «доза» аналогично выражению «для каждого», которое встречается во многих других языках программирования. Доза дозы в основном используется для итерации последовательности.

3 Dotimes заявление

Оператор «dotimes» используется для выполнения оператора «x» несколько раз.

4 Loop Statement

Специальная форма цикла не похожа на цикл for. Использование цикла такое же, как для привязки let. Тем не менее, цикл устанавливает точку рекурсии

Оператор while выполняется сначала путем вычисления выражения условия (логическое значение), и, если результат равен true, тогда выполняются операторы цикла while.

Утверждение «доза» аналогично выражению «для каждого», которое встречается во многих других языках программирования. Доза дозы в основном используется для итерации последовательности.

Оператор «dotimes» используется для выполнения оператора «x» несколько раз.

Специальная форма цикла не похожа на цикл for. Использование цикла такое же, как для привязки let. Тем не менее, цикл устанавливает точку рекурсии

Clojure — принятие решений

Структуры принятия решений требуют, чтобы программист указал одно или несколько условий, которые должны быть оценены или протестированы программой, вместе с оператором или инструкциями, которые должны быть выполнены, если условие определено как истинное, и, необязательно, другие операторы, которые должны быть выполнены, если условие определяется как ложное.

Sr.No. Методы и описание
1 Если заявление

В Clojure условие является выражением, которое оценивает его как истинное или ложное. «Если» условие истинно, то оператор # 1 будет выполнен, иначе оператор # 2 будет выполнен.

2 Если / сделать выражение

Выражение «if-do» в Clojure используется, чтобы разрешить выполнение нескольких выражений для каждой ветви оператора «if».

3 Вложенный оператор If

Множество операторов if встроены друг в друга.

4 Заявление о ситуации

Clojure предлагает оператор case, который похож на оператор switch, доступный в языке программирования Java.

5 Конд Заявление

Clojure предлагает еще одно оценочное утверждение, называемое «cond» . Этот оператор принимает набор пар test / expression.

В Clojure условие является выражением, которое оценивает его как истинное или ложное. «Если» условие истинно, то оператор # 1 будет выполнен, иначе оператор # 2 будет выполнен.

Выражение «if-do» в Clojure используется, чтобы разрешить выполнение нескольких выражений для каждой ветви оператора «if».

Множество операторов if встроены друг в друга.

Clojure предлагает оператор case, который похож на оператор switch, доступный в языке программирования Java.

Clojure предлагает еще одно оценочное утверждение, называемое «cond» . Этот оператор принимает набор пар test / expression.

Clojure — Функции

Clojure известен как функциональный язык программирования, поэтому вы ожидаете увидеть много внимания тому, как функции работают в Clojure. В этой главе рассказывается, что можно сделать с помощью функций в Clojure.

Sr.No. Функции и описание
1 Определение функции

Функция определяется с помощью макроса «defn» .

2 Анонимные функции

Анонимная функция — это функция, имя которой не связано с ней.

3 Функции с несколькими аргументами

Функции Clojure могут быть определены с нулевым или большим количеством параметров. Значения, которые вы передаете функциям, называются аргументами , и аргументы могут быть любого типа.

4 Вариадические функции

Clojure предлагает оператор case, который похож на оператор switch, доступный в языке программирования Java.

5 Функции высшего порядка

Функции высшего порядка (HOF) — это функции, которые принимают другие функции в качестве аргументов. HOF являются важной техникой функционального программирования и довольно часто используются в Clojure.

Функция определяется с помощью макроса «defn» .

Анонимная функция — это функция, имя которой не связано с ней.

Функции Clojure могут быть определены с нулевым или большим количеством параметров. Значения, которые вы передаете функциям, называются аргументами , и аргументы могут быть любого типа.

Clojure предлагает оператор case, который похож на оператор switch, доступный в языке программирования Java.

Функции высшего порядка (HOF) — это функции, которые принимают другие функции в качестве аргументов. HOF являются важной техникой функционального программирования и довольно часто используются в Clojure.

Clojure — Числа

Тип данных Numbers в Clojure является производным от классов Java.

Clojure поддерживает целые числа и числа с плавающей точкой.

  • Целое число — это значение, которое не включает дробь.

  • Число с плавающей запятой — это десятичное значение, которое включает десятичную дробь.

Целое число — это значение, которое не включает дробь.

Число с плавающей запятой — это десятичное значение, которое включает десятичную дробь.

Ниже приведен пример чисел в Clojure.

(def x 5)
(def y 5.25)

Где ‘x’ имеет тип Integer, а ‘y’ — это число с плавающей точкой .

В Java следующие классы привязаны к числам, определенным в Clojure.

чисел

Чтобы действительно увидеть, что числа в Clojure получены из классов Java, используйте следующую программу, чтобы увидеть тип чисел, назначенных при использовании команды ‘def’.

пример

Live Demo

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def x 5)
   (def y 5.25)
   (println (type x))
   (println (type y)))
(Example)

Команда «type» используется для вывода класса, связанного со значением, присвоенным переменной.

Выход

Приведенный выше код даст следующий вывод.

Java.lang.long
Java.lang.double

Числовые тесты

Следующие тестовые функции доступны для номеров.

Sr.No. Номера и описание
1 нуль?

Возвращает true, если число равно нулю, иначе false.

2 поз?

Возвращает true, если число больше нуля, иначе false.

3 нег?

Возвращает true, если число меньше нуля, иначе false.

4 четное?

Возвращает true, если число четное, и выдает исключение, если число не является целым числом.

5 странный?

Возвращает true, если число нечетное, и выдает исключение, если число не является целым числом.

6 число?

Возвращает true, если число действительно является Number.

7 целое число?

Возвращает true, если число является целым числом.

8 плавать?

Возвращает true, если число является числом с плавающей точкой.

Возвращает true, если число равно нулю, иначе false.

Возвращает true, если число больше нуля, иначе false.

Возвращает true, если число меньше нуля, иначе false.

Возвращает true, если число четное, и выдает исключение, если число не является целым числом.

Возвращает true, если число нечетное, и выдает исключение, если число не является целым числом.

Возвращает true, если число действительно является Number.

Возвращает true, если число является целым числом.

Возвращает true, если число является числом с плавающей точкой.

Clojure — рекурсия

Мы видели оператор recur в более ранней теме, и хотя цикл for напоминает цикл, recur — это реальный цикл в Clojure.

Если у вас есть опыт программирования, вы, возможно, слышали о хвостовой рекурсии, которая является основной особенностью функциональных языков. Эта рекурсивная специальная форма — та, которая реализует хвостовую рекурсию. Как указывает слово «рекурсия хвоста», рекурс должен вызываться в положении хвоста. Другими словами, recur должен быть последним, что нужно оценить.

Простейший пример оператора recur используется в цикле for. В следующем примере оператор recur используется для изменения значения переменной ‘i’ и передачи значения переменной обратно в выражение цикла.

пример

Live Demo

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (loop [i 0]
      (when (< i 5)
      (println i)
      (recur (inc i)))))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

0
1
2
3
4

Clojure — File I / O

Clojure предоставляет несколько вспомогательных методов при работе с вводом / выводом. Он предлагает более простые классы для обеспечения следующих функций для файлов.

  • Чтение файлов
  • Запись в файлы
  • Видя, является ли файл файлом или каталогом

Давайте рассмотрим некоторые файловые операции, которые предлагает Clojure.

Чтение содержимого файла как целой строки

Если вы хотите получить все содержимое файла в виде строки, вы можете использовать метод clojure.core.slurp . Команда slurp открывает читателя для файла и читает все его содержимое, возвращая строку.

Ниже приведен пример того, как это можно сделать.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def string1 (slurp "Example.txt"))
   (println string1))
(Example)

Если файл содержит следующие строки, они будут напечатаны как —

line : Example1
line : Example2

Чтение содержимого файла по одной строке за раз

Если вы хотите получить все содержимое файла в виде строки по одной строке за раз, вы можете использовать метод clojure.java.io/reader . Класс clojure.java.io/reader создает буфер чтения, который используется для чтения каждой строки файла.

Ниже приведен пример, который показывает, как это можно сделать.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (with-open [rdr (clojure.java.io/reader "Example.txt")]
   (reduce conj [] (line-seq rdr))))
(Example)

Если файл содержит следующие строки, они будут напечатаны как —

line : Example1
line : Example2

Результат будет показан как —

["line : Example1" "line : Example2"]

Запись в файлы

Если вы хотите записать «в» файлы, вы можете использовать команду clojure.core.spit, чтобы разбрасывать целые строки в файлы. Команда spit является противоположностью метода slurp. Этот метод открывает файл как писатель, записывает содержимое, а затем закрывает файл.

Ниже приведен пример.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (spit "Example.txt"
      "This is a string"))

В приведенном выше примере, если вы видите содержимое файла Example.txt, вы увидите содержимое «Это строка».

Запись в файлы по одной строке за раз

Если вы хотите записывать «в» файлы по одной строке за раз, вы можете использовать класс clojure.java.io.writer . Класс clojure.java.io.writer используется для создания потока записи, в котором байты данных передаются в поток, а затем в файл.

Ниже приведен пример, который показывает, как можно использовать команду spit.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (with-open [w (clojure.java.io/writer "Example.txt" :append true)]
      (.write w (str "hello" "world"))))
(Example)

Когда приведенный выше код будет выполнен, в файле Example.txt будет присутствовать строка «hello world». Параметр append: true предназначен для добавления данных в файл. Если эта опция не указана, то файл будет перезаписываться при записи данных в файл.

Проверка, существует ли файл

Чтобы проверить, существует ли файл, класс clojure.java.io.file можно использовать для проверки существования файла. Ниже приведен пример, который показывает, как это можно сделать.

(ns clojure.examples.hello
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println (.exists (clojure.java.io/file "Example.txt"))))
(Example)

Если файл Example.txt существует, вывод будет истинным.

Чтение с консоли

Для чтения данных из консоли можно использовать оператор read-line . Ниже приведен пример, который показывает, как это можно использовать.

Если вы введете команду (read-line) в окне REPL, у вас будет возможность ввести некоторые данные в окне консоли.

user->(read-line)
Hello World

Приведенный выше код даст следующий вывод.

“Hello World”

Clojure — Струны

Строковый литерал создается в Clojure, заключая текст строки в кавычки. Строки в Clojure должны быть построены с использованием двойных кавычек, таких как «Hello World».

пример

Ниже приведен пример использования строк в Clojure.

Live Demo

(ns clojure.examples.hello
   (:gen-class))
(defn hello-world []
   (println "Hello World")
   (println "This is a demo application"))
(hello-world)

Выход

Вышеуказанная программа производит следующий вывод.

Hello World
This is a demo application

Основные строковые операции

Clojure имеет ряд операций, которые можно выполнять со строками. Ниже приведены операции.

Sr.No. Строковые операции и описание
1 ул

Конкатенация строк может быть выполнена с помощью простой функции str.

2 формат

Форматирование строк может быть сделано с помощью простой функции форматирования. Функция форматирования форматирует строку, используя java.lang.String.format.

3 подсчитывать

Возвращает количество символов в строке.

4 подписка

Возвращает подстроку ‘s’, начиная с начала включительно и заканчивая в конце (по умолчанию длина строки), исключая.

5 сравнить

Возвращает отрицательное число, ноль или положительное число, когда «x» логически «меньше», «равно» или «больше, чем« y ».

6 в нижнем регистре

Преобразует строку во все строчные буквы.

7 верхний регистр

Преобразует строку в верхний регистр.

8 присоединиться

Возвращает строку всех элементов в коллекции, возвращаемую (seq collection), разделенных необязательным разделителем.

9 Трещина

Разбивает строку по регулярному выражению.

10 сплит-линия

Разделение строк основано на escape-символах \ n или \ r \ n.

11 задний ход

Меняет символы в строке.

12 замещать

Заменяет все совпадения в строке на строку замены.

13 отделка

Удаляет пробелы с обоих концов строки.

14 triml

Удаляет пробелы с левой стороны строки.

15 trimr

Удаляет пробелы с правой стороны строки.

Конкатенация строк может быть выполнена с помощью простой функции str.

Форматирование строк может быть сделано с помощью простой функции форматирования. Функция форматирования форматирует строку, используя java.lang.String.format.

Возвращает количество символов в строке.

Возвращает подстроку ‘s’, начиная с начала включительно и заканчивая в конце (по умолчанию длина строки), исключая.

Возвращает отрицательное число, ноль или положительное число, когда «x» логически «меньше», «равно» или «больше, чем« y ».

Преобразует строку во все строчные буквы.

Преобразует строку в верхний регистр.

Возвращает строку всех элементов в коллекции, возвращаемую (seq collection), разделенных необязательным разделителем.

Разбивает строку по регулярному выражению.

Разделение строк основано на escape-символах \ n или \ r \ n.

Меняет символы в строке.

Заменяет все совпадения в строке на строку замены.

Удаляет пробелы с обоих концов строки.

Удаляет пробелы с левой стороны строки.

Удаляет пробелы с правой стороны строки.

Clojure — Списки

Список — это структура, используемая для хранения коллекции элементов данных. В Clojure список реализует интерфейс ISeq . Списки создаются в Clojure с помощью функции списка.

пример

Ниже приведен пример создания списка чисел в Clojure.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (println (list 1 2 3 4)))
(example)

Выход

Приведенный выше код производит следующий вывод.

(1 2 3 4)

Ниже приведен пример создания списка символов в Clojure.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (println (list 'a 'b 'c 'd)))
(example)

Приведенный выше код производит следующий вывод.

(a b c d)

Ниже перечислены методы, доступные в Clojure.

Sr.No. Списки и описание
1 список*

Создает новый список, содержащий элементы, добавленные к остальным, последний из которых будет обрабатываться как последовательность.

2 первый

Эта функция возвращает первый элемент в списке.

3 энный

Эта функция возвращает элемент в n-й позиции в списке.

4 минусы

Возвращает новый список, в котором элемент добавляется в начало списка.

5 Призывание

Возвращает новый список, в котором список находится в начале, а добавляемые элементы помещаются в конец.

6 остальное

Возвращает оставшиеся элементы в списке после первого элемента.

Создает новый список, содержащий элементы, добавленные к остальным, последний из которых будет обрабатываться как последовательность.

Эта функция возвращает первый элемент в списке.

Эта функция возвращает элемент в n-й позиции в списке.

Возвращает новый список, в котором элемент добавляется в начало списка.

Возвращает новый список, в котором список находится в начале, а добавляемые элементы помещаются в конец.

Возвращает оставшиеся элементы в списке после первого элемента.

Clojure — Наборы

Наборы в Clojure — это набор уникальных значений. Наборы создаются в Clojure с помощью команды set.

пример

Ниже приведен пример создания множеств в Clojure.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (println (set '(1 1 2 2))))
(example)

Выход

Приведенный выше код производит следующий вывод.

#{1,2}

Ниже приведены методы, доступные в Clojure для наборов.

Sr.No. Наборы и описание
1 отсортированность набор

Возвращает отсортированный набор элементов.

2 получить

Возвращает элемент в позиции индекса.

3 содержит?

Выясняет, содержит ли набор определенный элемент или нет.

4 Призывание

Добавляет элемент в набор и возвращает новый набор элементов.

5 disj

Разъединяет элемент из набора.

6 союз

Вернуть набор, который является объединением входных наборов

7 разница

Вернуть набор, который является первым, без элементов остальных наборов.

8 пересечение

Вернуть набор, который является пересечением входных наборов.

9 подмножество?

Является ли set1 подмножеством set2?

10 надстройка?

Является ли set1 надмножеством set2?

Возвращает отсортированный набор элементов.

Возвращает элемент в позиции индекса.

Выясняет, содержит ли набор определенный элемент или нет.

Добавляет элемент в набор и возвращает новый набор элементов.

Разъединяет элемент из набора.

Вернуть набор, который является объединением входных наборов

Вернуть набор, который является первым, без элементов остальных наборов.

Вернуть набор, который является пересечением входных наборов.

Является ли set1 подмножеством set2?

Является ли set1 надмножеством set2?

Clojure — Векторы

Вектор — это набор значений, проиндексированных непрерывными целыми числами. Вектор создается с помощью векторного метода в Clojure.

пример

Ниже приведен пример создания вектора в Clojure.

Live Demo

(ns clojure.examples.example
   (:require [clojure.set :as set])
   (:gen-class))
(defn example []
   (println (vector 1 2 3)))
(example)

Выход

Приведенный выше код производит следующий вывод.

[1 2 3]

Ниже приведены методы, доступные в Clojure.

Sr.No. Векторы и описание
1 вектор-оф

Создает новый вектор одного примитивного типа ‘t’, где ‘t’ является одним из: int: long: float: double: byte: short: char или: boolean.

2 энный

Эта функция возвращает элемент в n-й позиции в векторе.

3 получить

Возвращает элемент в позиции индекса в векторе.

4 Призывание

Добавляет элемент в вектор и возвращает новый набор векторных элементов.

5 поп

Для списка или очереди возвращает новый список / очередь без первого элемента, для вектора — новый вектор без последнего элемента.

6 subvec

Возвращает субвектор из начального и конечного индекса.

Создает новый вектор одного примитивного типа ‘t’, где ‘t’ является одним из: int: long: float: double: byte: short: char или: boolean.

Эта функция возвращает элемент в n-й позиции в векторе.

Возвращает элемент в позиции индекса в векторе.

Добавляет элемент в вектор и возвращает новый набор векторных элементов.

Для списка или очереди возвращает новый список / очередь без первого элемента, для вектора — новый вектор без последнего элемента.

Возвращает субвектор из начального и конечного индекса.

Clojure — Карты

Карта — это коллекция, которая сопоставляет ключи со значениями. Предусмотрено два разных типа карт — хешированные и отсортированные. HashMaps требуют ключи, которые правильно поддерживают hashCode и равны. Для SortedMaps требуются ключи, которые реализуют Comparable, или экземпляр Comparator.

Карта может быть создана двумя способами, первый — с помощью метода hash-map.

Создание — HashMaps

HashMaps имеют типичное отношение ключ-значение и создаются с помощью функции hash-map.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (def demokeys (hash-map "z" "1" "b" "2" "a" "3"))
   (println demokeys))
(example)

Выход

Приведенный выше код производит следующий вывод.

{z 1, b 2, a 3}

Создание — SortedMaps

SortedMaps имеют уникальную характеристику сортировки своих элементов на основе ключевого элемента. Ниже приведен пример, который показывает, как отсортированная карта может быть создана с помощью функции sorted-map.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (def demokeys (sorted-map "z" "1" "b" "2" "a" "3"))
   (println demokeys))
(example)

Приведенный выше код производит следующий вывод.

{a 3, b 2, z 1}

Из приведенной выше программы вы можете четко видеть, что элементы на картах отсортированы по значению ключа. Ниже приведены методы, доступные для карт.

Sr.No. Карты и описание
1 получить

Возвращает значение, сопоставленное ключу, not-found или nil, если ключ отсутствует.

2 содержит?

Посмотрите, содержит ли карта требуемый ключ.

3 находить

Возвращает запись карты для ключа.

4 ключи

Возвращает список ключей на карте.

5 Vals

Возвращает список значений на карте.

6 dissoc

Разъединяет запись значения ключа с карты.

7 сливаться

Объединяет две записи карты в одну запись карты.

8 слиться с

Возвращает карту, которая состоит из остальных карт, соединенных с первой.

9 выберите клавиатурные

Возвращает карту, содержащую только те записи в карте, ключ которых находится в ключах.

10 переименовывать-ключи

Переименовывает ключи в текущем HashMap во вновь определенные.

11 Карта-инвертный

Инвертирует карты так, что значения становятся ключами, и наоборот.

Возвращает значение, сопоставленное ключу, not-found или nil, если ключ отсутствует.

Посмотрите, содержит ли карта требуемый ключ.

Возвращает запись карты для ключа.

Возвращает список ключей на карте.

Возвращает список значений на карте.

Разъединяет запись значения ключа с карты.

Объединяет две записи карты в одну запись карты.

Возвращает карту, которая состоит из остальных карт, соединенных с первой.

Возвращает карту, содержащую только те записи в карте, ключ которых находится в ключах.

Переименовывает ключи в текущем HashMap во вновь определенные.

Инвертирует карты так, что значения становятся ключами, и наоборот.

Clojure — Пространства имен

Пространства имен в Clojure используются для разделения классов на отдельные логические пространства, как в Java. Рассмотрим следующее утверждение.

(:require [clojure.set :as set])

В приведенном выше утверждении «clojure.set» является пространством имен, которое содержит различные классы и методы, которые будут использоваться в программе. Например, указанное пространство имен содержит функцию map-invert, которая используется для инвертирования карты значений ключей. Мы не можем использовать эту функцию, если мы явно не скажем нашей программе включить это пространство имен.

Давайте посмотрим на различные методы, доступные для пространств имен.

Sr.No. Методы и описание
1 * нс *

Это используется для просмотра вашего текущего пространства имен.

2 нс

Это используется для создания нового пространства имен и связывания его с работающей программой.

3 псевдоним

Добавьте псевдоним в текущем пространстве имен в другое пространство имен. Аргументами являются два символа: псевдоним, который будет использоваться, и символическое имя целевого пространства имен.

4 все нс

Возвращает список всех пространств имен.

5 найти нс

Находит и возвращает определенное пространство имен.

6 нс-имя

Возвращает имя определенного пространства имен.

7 нс-псевдонимы

Возвращает псевдонимы, которые связаны с любыми пространствами имен.

8 нс-карта

Возвращает карту всех отображений для пространства имен.

9 ип-псевдоним

Возвращает карту, содержащую только те записи в карте, ключ которых находится в ключах.

Это используется для просмотра вашего текущего пространства имен.

Это используется для создания нового пространства имен и связывания его с работающей программой.

Добавьте псевдоним в текущем пространстве имен в другое пространство имен. Аргументами являются два символа: псевдоним, который будет использоваться, и символическое имя целевого пространства имен.

Возвращает список всех пространств имен.

Находит и возвращает определенное пространство имен.

Возвращает имя определенного пространства имен.

Возвращает псевдонимы, которые связаны с любыми пространствами имен.

Возвращает карту всех отображений для пространства имен.

Возвращает карту, содержащую только те записи в карте, ключ которых находится в ключах.

Clojure — обработка исключений

Обработка исключений требуется на любом языке программирования для обработки ошибок времени выполнения, чтобы можно было поддерживать нормальный поток приложения. Исключение обычно нарушает нормальный поток приложения, поэтому мы должны использовать обработку исключений в нашем приложении.

Исключение широко классифицируется на следующие категории —

  • Проверенное исключение — классы, которые расширяют класс Throwable, кроме RuntimeException и Error, называются проверенными исключениями. Например, IOException, SQLException и т. Д. Проверенные исключения проверяются во время компиляции.

Проверенное исключение — классы, которые расширяют класс Throwable, кроме RuntimeException и Error, называются проверенными исключениями. Например, IOException, SQLException и т. Д. Проверенные исключения проверяются во время компиляции.

Давайте рассмотрим следующую программу, которая выполняет операцию над файлом с именем Example.txt. Однако всегда может быть случай, когда файл Example.txt не существует.

Live Demo

(ns clojure.examples.example
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def string1 (slurp "Example.txt"))
   (println string1))
(Example)

Если файл Example.txt не существует, программа создаст следующее исключение.

Caused by: java.io.FileNotFoundException: Example.txt (No such file or
directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at clojure.java.io$fn__9185.invoke(io.clj:229)
at clojure.java.io$fn__9098$G__9091__9105.invoke(io.clj:69)
at clojure.java.io$fn__9197.invoke(io.clj:258)
at clojure.java.io$fn__9098$G__9091__9105.invoke(io.clj:69)

Из вышеупомянутого исключения мы можем ясно видеть, что программа вызвала исключение FileNotFoundException.

  • Непроверенное исключение — классы, которые расширяют RuntimeException, называются непроверенными исключениями. Например, ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException и т. Д. Непроверенные исключения не проверяются во время компиляции, а проверяются во время выполнения.

Непроверенное исключение — классы, которые расширяют RuntimeException, называются непроверенными исключениями. Например, ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException и т. Д. Непроверенные исключения не проверяются во время компиляции, а проверяются во время выполнения.

Одним классическим случаем является исключение ArrayIndexOutOfBoundsException, которое возникает, когда вы пытаетесь получить доступ к индексу массива, который больше длины массива. Ниже приведен типичный пример ошибки такого рода.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (aget (int-array [1 2 3]) 5)
      (catch Exception e (println (str "caught exception: " (.toString e))))
      (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

Когда приведенный выше код выполняется, возникает следующее исключение.

caught exception: java.lang.ArrayIndexOutOfBoundsException: 5
This is our final block
Let's move on

ошибка

Ошибка необратима, например, OutOfMemoryError, VirtualMachineError, AssertionError и т. Д. Это ошибки, из-за которых программа никогда не сможет восстановиться и приведет к ее аварийному завершению. Теперь нам нужен механизм для перехвата этих исключений, чтобы программа могла продолжать работать, если такие исключения существуют.

Следующая диаграмма показывает, как организована иерархия исключений в Clojure. Все это основано на иерархии, определенной в Java.

Исключения в Clojure

Ловить исключения

Как и другие языки программирования, Clojure предоставляет обычный блок try-catch для перехвата исключений по мере их возникновения.

Ниже приведен общий синтаксис блока try-catch.

(try
   (//Protected code)
   catch Exception e1)
(//Catch block)

Весь ваш код, который может вызвать исключение, помещается в блок защищенного кода .

В блоке catch вы можете написать собственный код для обработки вашего исключения, чтобы приложение могло восстановиться после исключения.

Давайте посмотрим на наш предыдущий пример, который сгенерировал исключение «файл не найден», и посмотрим, как мы можем использовать блок try catch для перехвата исключения, созданного программой.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      (catch Exception e (println (str "caught exception: " (.getMessage e))))))
(Example)

Вышеуказанная программа производит следующий вывод.

caught exception: Example.txt (No such file or directory)

Из приведенного выше кода мы оборачиваем неисправный код в блоке try . В блоке catch мы просто перехватываем наше исключение и выводим сообщение о том, что произошло исключение. Итак, теперь у нас есть осмысленный способ захвата исключения, которое генерируется программой.

Многократные Пойманные Блоки

Можно иметь несколько блоков catch для обработки нескольких типов исключений. Для каждого блока catch, в зависимости от типа возникшего исключения, вы должны написать код для соответствующей обработки.

Давайте изменим наш предыдущий код, включив в него два блока catch, один из которых относится к исключению для нашего файла not found, а другой — к блоку общего исключения.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.getMessage e))))
      
      (catch Exception e (println (str "caught exception: " (.getMessage e)))))
   (println "Let's move on"))
(Example)

Вышеуказанная программа производит следующий вывод.

caught file exception: Example.txt (No such file or directory)
Let's move on

Из вышеприведенного вывода мы ясно видим, что наше исключение было перехвачено блоком перехвата FileNotFoundException, а не общим.

Наконец-то блок

Блок finally следует за блоком try или блоком catch. Блок кода finally всегда выполняется независимо от возникновения исключения.

Использование блока finally позволяет запускать любые операторы типа очистки, которые вы хотите выполнить, независимо от того, что происходит в защищенном коде. Ниже приводится синтаксис этого блока.

(try
   (//Protected code)
   catch Exception e1)
(//Catch block)
(finally
   //Cleanup code)

Давайте изменим приведенный выше код и добавим блок finally. Ниже приведен фрагмент кода.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.getMessage e))))
      
      (catch Exception e (println (str "caught exception: " (.getMessage e))))
      (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

Вышеуказанная программа производит следующий вывод.

caught file exception: Example.txt (No such file or directory)
This is our final block
Let's move on

Из приведенной выше программы видно, что последний блок также реализован после того, как блок catch перехватывает требуемое исключение.

Поскольку Clojure получает обработку исключений из Java, подобно Java, в Clojure доступны следующие методы для управления исключениями.

  • public String getMessage () — возвращает подробное сообщение об исключении, которое произошло. Это сообщение инициализируется в конструкторе Throwable.

  • public Throwable getCause () — Возвращает причину исключения, представленного объектом Throwable.

  • public String toString () — Возвращает имя класса, объединенного с результатом getMessage ().

  • public void printStackTrace () — печатает результат toString () вместе с трассировкой стека в System.err, поток вывода ошибок.

  • public StackTraceElement [] getStackTrace () — Возвращает массив, содержащий каждый элемент в трассировке стека. Элемент с индексом 0 представляет вершину стека вызовов, а последний элемент в массиве представляет метод в нижней части стека вызовов.

  • public Throwable fillInStackTrace () — Заполняет трассировку стека этого объекта Throwable текущей трассировкой стека, добавляя к любой предыдущей информации в трассировке стека.

public String getMessage () — возвращает подробное сообщение об исключении, которое произошло. Это сообщение инициализируется в конструкторе Throwable.

public Throwable getCause () — Возвращает причину исключения, представленного объектом Throwable.

public String toString () — Возвращает имя класса, объединенного с результатом getMessage ().

public void printStackTrace () — печатает результат toString () вместе с трассировкой стека в System.err, поток вывода ошибок.

public StackTraceElement [] getStackTrace () — Возвращает массив, содержащий каждый элемент в трассировке стека. Элемент с индексом 0 представляет вершину стека вызовов, а последний элемент в массиве представляет метод в нижней части стека вызовов.

public Throwable fillInStackTrace () — Заполняет трассировку стека этого объекта Throwable текущей трассировкой стека, добавляя к любой предыдущей информации в трассировке стека.

Ниже приведен пример кода, который использует некоторые из методов, перечисленных выше.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (try
      (def string1 (slurp "Example.txt"))
      (println string1)
      
      (catch java.io.FileNotFoundException e (println (str "caught file
         exception: " (.toString e))))
      
      (catch Exception e (println (str "caught exception: " (.toString e))))
   (finally (println "This is our final block")))
   (println "Let's move on"))
(Example)

Вышеуказанная программа производит следующий вывод.

caught file exception: java.io.FileNotFoundException: Example.txt (No such file
or directory)
This is our final block
Let's move on

Clojure — последовательности

Последовательности создаются с помощью команды seq . Ниже приведен простой пример создания последовательности.

Live Demo

(ns clojure.examples.example
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (println (seq [1 2 3])))
(Example)

Вышеуказанная программа производит следующий вывод.

(1 2 3)

Ниже приведены различные методы, доступные для последовательностей.

Sr.No. Методы и описание
1 минусы

Возвращает новую последовательность, где «x» является первым элементом, а «seq» — остальным.

2 Призывание

Возвращает новую последовательность, где «x» — это элемент, который добавляется в конец последовательности.

3 CONCAT

Это используется для объединения двух последовательностей.

4 отчетливый

Используется только для того, чтобы обеспечить добавление отдельных элементов в последовательность.

5 задний ход

Инвертирует элементы в последовательности.

6 первый

Возвращает первый элемент последовательности.

7 прошлой

Возвращает последний элемент последовательности.

8 остальное

Возвращает всю последовательность, кроме первого элемента.

9 Сортировать

Возвращает отсортированную последовательность элементов.

10 падение

Удаляет элементы из последовательности на основе количества элементов, которое необходимо удалить.

11 бери последний

Принимает последний список элементов из последовательности.

12 принимать

Принимает первый список элементов из последовательности.

13 сплит-на

Разбивает последовательность предметов на две части. Указывается местоположение, в котором должно произойти разделение.

Возвращает новую последовательность, где «x» является первым элементом, а «seq» — остальным.

Возвращает новую последовательность, где «x» — это элемент, который добавляется в конец последовательности.

Это используется для объединения двух последовательностей.

Используется только для того, чтобы обеспечить добавление отдельных элементов в последовательность.

Инвертирует элементы в последовательности.

Возвращает первый элемент последовательности.

Возвращает последний элемент последовательности.

Возвращает всю последовательность, кроме первого элемента.

Возвращает отсортированную последовательность элементов.

Удаляет элементы из последовательности на основе количества элементов, которое необходимо удалить.

Принимает последний список элементов из последовательности.

Принимает первый список элементов из последовательности.

Разбивает последовательность предметов на две части. Указывается местоположение, в котором должно произойти разделение.

Clojure — регулярные выражения

Регулярное выражение — это шаблон, который используется для поиска подстрок в тексте. Регулярные выражения используются во множестве языков программирования и часто используются в языках программирования типа LISP.

Ниже приведен пример регулярного выражения.

//d+

Приведенное выше регулярное выражение используется для поиска еще одного вхождения цифры в строку. Символы // используются для обеспечения того, чтобы символы «d» и «+» использовались для представления регулярного выражения.

Как правило, регулярные выражения работают со следующим набором правил.

  • Есть два специальных позиционных символа, которые используются для обозначения начала и конца строки: символ каретки (∧) и знак доллара ($):

  • Регулярные выражения также могут включать квантификаторы. Знак плюс (+) представляет один или несколько раз, примененных к предыдущему элементу выражения. Звездочка (*) используется для обозначения нуля или более вхождений. Знак вопроса (?) Обозначает ноль или один раз.

  • Метасимвол {и} используется для соответствия определенному количеству экземпляров предыдущего символа.

  • В регулярном выражении символ точки (.) Может представлять любой символ. Это описано как символ подстановки.

  • Регулярное выражение может включать в себя классы символов. Набор символов может быть задан в виде простой последовательности символов, заключенных в метасимволы [и], как в [aeiou]. Для диапазонов букв или чисел вы можете использовать разделитель тире, как в [a – z] или [a – mA – M]. Дополнение к символьному классу обозначается ведущим символом в квадратных скобках, как в [–a – z], и представляет все символы, отличные от указанных.

Есть два специальных позиционных символа, которые используются для обозначения начала и конца строки: символ каретки (∧) и знак доллара ($):

Регулярные выражения также могут включать квантификаторы. Знак плюс (+) представляет один или несколько раз, примененных к предыдущему элементу выражения. Звездочка (*) используется для обозначения нуля или более вхождений. Знак вопроса (?) Обозначает ноль или один раз.

Метасимвол {и} используется для соответствия определенному количеству экземпляров предыдущего символа.

В регулярном выражении символ точки (.) Может представлять любой символ. Это описано как символ подстановки.

Регулярное выражение может включать в себя классы символов. Набор символов может быть задан в виде простой последовательности символов, заключенных в метасимволы [и], как в [aeiou]. Для диапазонов букв или чисел вы можете использовать разделитель тире, как в [a – z] или [a – mA – M]. Дополнение к символьному классу обозначается ведущим символом в квадратных скобках, как в [–a – z], и представляет все символы, отличные от указанных.

Следующие методы доступны для регулярных выражений.

Sr.No. Методы и описание
1 повторно шаблон

Возвращает экземпляр java.util.regex.Pattern. Это затем используется в дальнейших методах для сопоставления с образцом.

2 refind

Возвращает следующее совпадение регулярного выражения, если оно есть, строки с шаблоном, используя java.util.regex.Matcher.find ()

3 замещать

Функция замены используется для замены подстроки в строке новым строковым значением. Поиск подстроки выполняется с использованием шаблона.

4 заменить первый

Функция замены используется для замены подстроки в строке новым строковым значением, но только для первого вхождения подстроки. Поиск подстроки выполняется с использованием шаблона.

Возвращает экземпляр java.util.regex.Pattern. Это затем используется в дальнейших методах для сопоставления с образцом.

Возвращает следующее совпадение регулярного выражения, если оно есть, строки с шаблоном, используя java.util.regex.Matcher.find ()

Функция замены используется для замены подстроки в строке новым строковым значением. Поиск подстроки выполняется с использованием шаблона.

Функция замены используется для замены подстроки в строке новым строковым значением, но только для первого вхождения подстроки. Поиск подстроки выполняется с использованием шаблона.

Clojure — Предикаты

Предикаты — это функции, которые оценивают условие и предоставляют значение true или false. Мы видели предикатные функции в примерах главы о числах. Мы видели такие функции, как «даже?» который используется для проверки, является ли число четным или нет, или ‘neg?’ который используется для проверки, если число больше нуля или нет. Все эти функции возвращают либо истинное, либо ложное значение.

Ниже приведен пример предикатов в Clojure.

Live Demo

(ns clojure.examples.example
   (:gen-class))

;; This program displays Hello World
(defn Example []
   (def x (even? 0))
   (println x)
   
   (def x (neg? 2))
   (println x)
   
   (def x (odd? 3))
   (println x)
   
   (def x (pos? 3))
   (println x))
(Example)

Вышеуказанная программа производит следующий вывод.

true
false
true
true

В дополнение к обычным функциям предикатов Clojure предоставляет больше функций для предикатов. Для предикатов доступны следующие методы.

Sr.No. Методы и описание
1 каждый-пред

Принимает набор предикатов и возвращает функцию ‘f’, которая возвращает значение true, если все его составные предикаты возвращают логическое значение true для всех своих аргументов, в противном случае возвращает значение false.

2 каждый?

Возвращает true, если предикат имеет значение true для каждого значения, иначе false.

3 немного

Возвращает первое логическое истинное значение для любого значения предиката x в коллекции значений.

4 не-никакой?

Возвращает false, если любой из предикатов значений в коллекции логически истинен, в противном случае — истина.

Принимает набор предикатов и возвращает функцию ‘f’, которая возвращает значение true, если все его составные предикаты возвращают логическое значение true для всех своих аргументов, в противном случае возвращает значение false.

Возвращает true, если предикат имеет значение true для каждого значения, иначе false.

Возвращает первое логическое истинное значение для любого значения предиката x в коллекции значений.

Возвращает false, если любой из предикатов значений в коллекции логически истинен, в противном случае — истина.

Clojure — Разрушение

Разрушение — это функциональность в Clojure, которая позволяет извлекать значения из структуры данных, такой как вектор, и связывать их с символами без необходимости явного обхода структуры данных.

Давайте рассмотрим пример того, что именно означает разрушение и как это происходит.

пример

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-vector [1 2 3 4])
   (let [[a b c d] my-vector]
   (println a b c d)))
(Example)

Вышеуказанная программа производит следующий вывод.

Выход

1 2 3 4

В приведенном выше примере следует отметить следующее:

  • Мы определяем вектор целых чисел как 1, 2, 3 и 4.

  • Затем мы используем оператор let для непосредственного присвоения 4 переменных (a, b, c и d) переменной my-vector.

  • Если мы запустим оператор println для четырех переменных, мы увидим, что они уже были присвоены значениям в векторе соответственно.

Мы определяем вектор целых чисел как 1, 2, 3 и 4.

Затем мы используем оператор let для непосредственного присвоения 4 переменных (a, b, c и d) переменной my-vector.

Если мы запустим оператор println для четырех переменных, мы увидим, что они уже были присвоены значениям в векторе соответственно.

Таким образом, clojure деструктурировал переменную my-vector, которая имеет четыре значения, когда она была назначена с помощью оператора let. Затем четыре деконструированных значения были назначены четырем параметрам соответственно.

Если есть избыточные переменные, которые не имеют соответствующего значения, которому они могут быть назначены, тогда им будет присвоено значение nil. Следующий пример проясняет этот момент.

пример

Live Demo

(ns clojure.examples.hello
   (:gen-class))
(defn Example []
   (def my-vector [1 2 3 4])
   (let [[a b c d e] my-vector]
   (println a b c d e)))
(Example)

Вышеуказанная программа производит следующий вывод. Из выходных данных видно, что, поскольку последняя переменная ‘e’ не имеет соответствующего значения в векторе, она равна нулю.

Выход

1 2 3 4 nil

остальные

Переменная ‘the-rest’ используется для хранения оставшихся значений, которые не могут быть присвоены какой-либо переменной.

Пример того, как это используется, показан в следующей программе.

пример

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-vector [1 2 3 4])
   (let [[a b & the-rest] my-vector]
   (println a b the-rest)))
(Example)

Вышеуказанная программа производит следующий вывод. Из выходных данных вы можете ясно видеть, что значения 3 и 4 не могут быть назначены какой-либо переменной, поэтому они присваиваются переменной ‘the-rest’.

Выход

1 2 (3 4)

Карты разрушения

Карты, как и векторы, также могут быть деструктурированы. Ниже приведен пример того, как это можно сделать.

пример

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-map {"a" 1 "b" 2})
   (let [{a "a" b "b"} my-map]
   (println a b)))
(Example)

Вышеуказанная программа производит следующий вывод. Из программы вы можете ясно видеть, что значения карты «a» и «b» присваиваются переменным a и b.

Выход

1 2

Точно так же в случае векторов, если на карте нет соответствующего значения, когда происходит деструктуризация, переменной будет присвоено значение nil.

Ниже приведен пример.

пример

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def my-map {"a" 1 "b" 2})
   (let [{a "a" b "b" c "c"} my-map]
   (println a b c)))
(Example)

Вышеуказанная программа производит следующий вывод.

Выход

1 2 nil

Clojure — дата и время

Поскольку платформа Clojure является производной от классов Java, можно использовать классы даты и времени, доступные в Java в Clojure. Дата класса представляет определенный момент времени с точностью до миллисекунды.

Ниже приведены методы, доступные для класса дата-время.

java.util.Date

Это используется для создания объекта даты в Clojure.

Синтаксис

Ниже приводится синтаксис.

java.util.Date.

Параметры — Нет.

Возвращаемое значение — выделяет объект Date и инициализирует его так, чтобы он представлял время, в которое он был выделен, с точностью до миллисекунды.

пример

Пример того, как это используется, показан в следующей программе.

Live Demo

(ns example)
(defn Example []
   (def date (.toString (java.util.Date.)))
   (println date))
(Example)

Выход

Вышеуказанная программа производит следующий вывод. Это будет зависеть от текущей даты и времени в системе, в которой выполняется программа.

Tue Mar 01 06:11:17 UTC 2016

java.text.SimpleDateFormat

Это используется для форматирования вывода даты.

Синтаксис

Ниже приводится синтаксис.

(java.text.SimpleDateFormat. format dt)

Параметры — «формат» — это формат, который будет использоваться при форматировании даты. ‘dt’ — это дата, которую нужно отформатировать.

Возвращаемое значение — форматированный вывод даты.

пример

Пример того, как это используется, показан в следующей программе.

Live Demo

(ns example)
(defn Example []
   (def date (.format (java.text.SimpleDateFormat. "MM/dd/yyyy") (new java.util.Date)))
   (println date))
(Example)

Выход

Вышеуказанная программа производит следующий вывод. Это будет зависеть от текущей даты и времени в системе, в которой выполняется программа.

03/01/2016

GetTime

Возвращает количество миллисекунд с 1 января 1970 года, 00:00:00 по Гринвичу, представленное этим объектом Date.

Синтаксис

Ниже приводится синтаксис.

(.getTime)

Параметры — Нет.

Возвращаемое значение — количество миллисекунд с 1 января 1970 года, 00:00:00 по Гринвичу, представленное этой датой.

пример

Пример того, как это используется, показан в следующей программе.

Live Demo

(ns example)
(import java.util.Date)
(defn Example []
   (def date (.getTime (java.util.Date.)))
   (println date))
(Example)

Выход

Вышеуказанная программа производит следующий вывод. Это будет зависеть от текущей даты и времени в системе, в которой выполняется программа.

1456812778160

Clojure — Атомы

Атомы — это тип данных в Clojure, который предоставляет способ управления общим, синхронным, независимым состоянием. Атом похож на любой ссылочный тип в любом другом языке программирования. Основное использование атома — хранение неизменяемых структур данных Clojure. Значение, удерживаемое атомом, изменяется со свопом! метод .

Внутренне поменяйся! читает текущее значение, применяет к нему функцию и пытается сравнить и установить его. Поскольку другой поток мог изменить значение за прошедшее время, ему, возможно, придется повторить попытку, и это происходит в цикле вращения. Чистый эффект состоит в том, что значение всегда будет результатом применения предоставленной функции к текущему значению атомарно.

пример

Атомы создаются с помощью метода атома. Пример того же показан в следующей программе.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn example []
   (def myatom (atom 1))
   (println @myatom))
(example)

Выход

Вышеуказанная программа дает следующий результат.

1

Доступ к значению atom осуществляется с помощью символа @. Clojure имеет несколько операций, которые могут быть выполнены на атомах. Ниже приведены операции.

Sr.No. Операции и описание
1 сброс!

Устанавливает значение атома в новое значение без учета текущего значения.

2 сравнения и набор!

Атомно устанавливает значение атома в новое значение тогда и только тогда, когда текущее значение атома идентично старому значению атома. Возвращает true, если установлено, иначе возвращает false.

3 своп!

Атомно меняет значение атома на новое, основанное на определенной функции.

Устанавливает значение атома в новое значение без учета текущего значения.

Атомно устанавливает значение атома в новое значение тогда и только тогда, когда текущее значение атома идентично старому значению атома. Возвращает true, если установлено, иначе возвращает false.

Атомно меняет значение атома на новое, основанное на определенной функции.

Clojure — Метаданные

В Clojure метаданные используются для аннотирования данных в коллекции или для данных, хранящихся в символе. Обычно это используется для аннотирования данных о типах в базовом компиляторе, но также может использоваться для разработчиков. Метаданные не считаются частью стоимости объекта. В то же время метаданные неизменны.

Следующие операции возможны в Clojure в отношении метаданных.

Sr.No. Операции и описание
1 мета-с

Эта функция используется для определения карты метаданных для любого объекта.

2 мета

Эта функция используется, чтобы увидеть, связаны ли какие-либо метаданные с объектом.

3 варьироваться в мета-

Возвращает объект того же типа и значения, что и исходный объект, но с комбинированными метаданными.

Эта функция используется для определения карты метаданных для любого объекта.

Эта функция используется, чтобы увидеть, связаны ли какие-либо метаданные с объектом.

Возвращает объект того же типа и значения, что и исходный объект, но с комбинированными метаданными.

Clojure — StructMaps

StructMaps используются для создания структур в Clojure. Например, если вы хотите создать структуру, состоящую из имени сотрудника и идентификатора сотрудника, вы можете сделать это с помощью StructMaps.

Следующие операции возможны в Clojure в отношении StructMaps.

Sr.No. Операции и описание
1 defstruct

Эта функция используется для определения структуры, которая требуется.

2 структура

Эта функция используется для определения объекта структуры типа, который создается операцией defstruct.

3 структура-карта

Эта функция используется для точного присвоения значений ключевым значениям путем явного определения того, какие значения назначены каким ключам в структуре.

4 Доступ к отдельным полям

К отдельным полям структуры можно получить доступ, используя ключи вместе с объектом структуры.

5 Неизменная природа

По умолчанию структуры также являются неизменяемыми, поэтому, если мы попытаемся изменить значение определенного ключа, оно не изменится.

6 Добавление нового ключа в структуру

Поскольку структуры являются неизменяемыми, единственный способ добавить другой ключ в структуру — это создать новую структуру. Пример того, как этого можно достичь, показан в следующей программе.

Эта функция используется для определения структуры, которая требуется.

Эта функция используется для определения объекта структуры типа, который создается операцией defstruct.

Эта функция используется для точного присвоения значений ключевым значениям путем явного определения того, какие значения назначены каким ключам в структуре.

К отдельным полям структуры можно получить доступ, используя ключи вместе с объектом структуры.

По умолчанию структуры также являются неизменяемыми, поэтому, если мы попытаемся изменить значение определенного ключа, оно не изменится.

Поскольку структуры являются неизменяемыми, единственный способ добавить другой ключ в структуру — это создать новую структуру. Пример того, как этого можно достичь, показан в следующей программе.

Clojure — Агенты

Как уже много раз указывалось, Clojure — это язык программирования, в котором многие типы данных являются неизменяемыми, что означает, что единственный способ изменить значение переменной — это создать новую переменную и присвоить ей новое значение. Однако Clojure предоставляет некоторые элементы, которые могут создавать изменяемое состояние. Мы видели, что этого можно достичь с помощью типа данных atom. Другой способ добиться этого — через агентов.

Агенты обеспечивают независимую, асинхронную смену отдельных местоположений. Агенты привязаны к одному хранилищу в течение своего срока службы и допускают только мутацию этого местоположения (в новое состояние) в результате действия. Действия — это функции (с, необязательно, дополнительными аргументами), которые асинхронно применяются к состоянию Агента и возвращаемое значение которых становится новым состоянием Агента.

Следующие операции возможны в Clojure в отношении Агентов.

Sr.No. Операции и описание
1 агент

Агент создается с помощью команды агента.

2 Отправить

Эта функция используется для отправки значения агенту.

3 выключение агенты

Эта функция используется для выключения любых работающих агентов.

4 отослать

В некоторых случаях агенту назначается функция, которая по своей природе блокирует.

5 жду, для

Поскольку при обновлении значения агента существует задержка, Clojure предоставила функцию «ожидания», которая используется для указания времени в миллисекундах, в течение которого следует ожидать обновления агента.

6 Ждите

Блокирует текущий поток (на неопределенный срок!) До тех пор, пока не будут выполнены все действия, отправленные до сих пор из этого потока или агента агенту (агентам). Будет заблокирован на сбой агентов.

7 Агент ошибок

Возвращает исключение, выданное во время асинхронного действия агента, если агент завершается ошибкой. Возвращает ноль, если агент не терпит неудачу.

Агент создается с помощью команды агента.

Эта функция используется для отправки значения агенту.

Эта функция используется для выключения любых работающих агентов.

В некоторых случаях агенту назначается функция, которая по своей природе блокирует.

Поскольку при обновлении значения агента существует задержка, Clojure предоставила функцию «ожидания», которая используется для указания времени в миллисекундах, в течение которого следует ожидать обновления агента.

Блокирует текущий поток (на неопределенный срок!) До тех пор, пока не будут выполнены все действия, отправленные до сих пор из этого потока или агента агенту (агентам). Будет заблокирован на сбой агентов.

Возвращает исключение, выданное во время асинхронного действия агента, если агент завершается ошибкой. Возвращает ноль, если агент не терпит неудачу.

Clojure — Наблюдатели

Наблюдатели — это функции, добавляемые к типам переменных, таким как атомы и ссылочные переменные, которые вызываются при изменении значения типа переменной. Например, если вызывающая программа изменяет значение переменной атома, и если функция переменной наблюдателя присоединена к переменной атома, функция будет вызвана, как только значение атома будет изменено.

Следующие функции доступны в Clojure для наблюдателей.

надстройку часы

Добавляет функцию наблюдения в ссылку agent / atom / var / ref. Часы ‘fn’ должны быть ‘fn’ из 4 аргументов: ключ, ссылка, его старое состояние, его новое состояние. Всякий раз, когда состояние ссылки могло быть изменено, любые зарегистрированные часы будут вызывать свои функции.

Синтаксис

Ниже приводится синтаксис.

(add-watch variable :watcher
   (fn [key variable-type old-state new-state]))

Параметры — переменная — это имя атома или ссылочной переменной. ‘тип переменной’ — это тип переменной, атом или ссылочная переменная. ‘old-state & new-state’ — это параметры, которые будут автоматически хранить старое и новое значение переменной. «Ключ» должен быть уникальным для каждой ссылки и может использоваться для удаления часов с помощью remove-watch.

Возвращаемое значение — Нет.

пример

Пример того, как это используется, показан в следующей программе.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def x (atom 0))
   (add-watch x :watcher
      (fn [key atom old-state new-state]
      (println "The value of the atom has been changed")
      (println "old-state" old-state)
      (println "new-state" new-state)))
(reset! x 2))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

The value of the atom has been changed
old-state 0
new-state 2

удалить-часы

Удаляет часы, которые были прикреплены к ссылочной переменной.

Синтаксис

Ниже приводится синтаксис.

(remove-watch variable watchname)

Параметры — переменная — это имя атома или ссылочной переменной. ‘watchname’ — это имя, данное часам при определении функции часов.

Возвращаемое значение — Нет.

пример

Пример того, как это используется, показан в следующей программе.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def x (atom 0))
   (add-watch x :watcher
      (fn [key atom old-state new-state]
         (println "The value of the atom has been changed")
         (println "old-state" old-state)
         (println "new-state" new-state)))
   (reset! x 2)
   (remove-watch x :watcher)
(reset! x 4))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

The value of the atom has been changed
old-state 0
new-state 2

Из вышеприведенной программы вы можете четко видеть, что вторая команда сброса не вызывает наблюдателя, поскольку она была удалена из списка наблюдателя.

Clojure — Макросы

На любом языке макросы используются для генерации встроенного кода. Clojure не является исключением и предоставляет простые средства макросов для разработчиков. Макросы используются для написания процедур генерации кода, которые предоставляют разработчику мощный способ адаптировать язык к потребностям разработчика.

Ниже приведены методы, доступные для макросов.

defmacro

Эта функция используется для определения вашего макроса. Макрос будет иметь имя макроса, список параметров и тело макроса.

Синтаксис

Ниже приводится синтаксис.

(defmacro name [params*] body)

Параметры — ‘name’ — это имя макроса. «params» — это параметры, назначенные макросу. «тело» — это тело макроса.

Возвращаемое значение — Нет.

пример

Пример того, как это используется, показан в следующей программе.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (defmacro Simple []
      (println "Hello"))
   (macroexpand '(Simple)))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

Hello

Из вышеприведенной программы вы можете видеть, что макрос «Simple» встроен в «println» «Hello». Макросы похожи на функции, с той лишь разницей, что аргументы формы оцениваются в случае макросов.

макро-расширение

Это используется для расширения макроса и размещения встроенного кода в программе.

Синтаксис

Ниже приводится синтаксис.

(macroexpand macroname)

Параметры — «macroname» — это имя макроса, который необходимо расширить.

Возвращаемое значение — расширенный макрос.

пример

Пример того, как это используется, показан в следующей программе.

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (defmacro Simple []
      (println "Hello"))
   (macroexpand '(Simple)))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

Hello

Макрос с аргументами

Макросы также можно использовать для аргументов. Макрос может принимать любое количество аргументов. В следующем примере показано, как можно использовать аргументы.

пример

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (defmacro Simple [arg]
      (list 2 arg))
   (println (macroexpand '(Simple 2))))
(Example)

Приведенный выше пример помещает аргумент в макрос Simple и затем использует аргумент для добавления значения аргумента в список.

Выход

Вышеуказанная программа производит следующий вывод.

(2 2)

Clojure — справочные значения

Ссылочные значения — это еще один способ, которым Clojure может работать с требованием иметь изменяемые переменные. Clojure предоставляет изменяемые типы данных, такие как атомы, агенты и ссылочные типы.

Ниже приведены операции, доступные для справочных значений.

Sr.No. Операции и описание
1 ссылка

Это используется для создания ссылочного значения. При создании ссылочного значения есть возможность предоставить функцию валидатора, которая будет проверять созданное значение.

2 реф-набор

Эта функция используется для установки значения ссылки на новое значение независимо от того, что является более старым значением.

3 изменять

Эта функция используется для изменения значения ссылочного типа, но безопасным способом. Это выполняется в потоке, к которому другой процесс не может получить доступ.

4 dosync

Запускает выражение (в неявном do) в транзакции, которая включает выражение и любые вложенные вызовы.

5 ездить

Commute также используется для изменения значения ссылочного типа, как alter и ref-set.

Это используется для создания ссылочного значения. При создании ссылочного значения есть возможность предоставить функцию валидатора, которая будет проверять созданное значение.

Эта функция используется для установки значения ссылки на новое значение независимо от того, что является более старым значением.

Эта функция используется для изменения значения ссылочного типа, но безопасным способом. Это выполняется в потоке, к которому другой процесс не может получить доступ.

Запускает выражение (в неявном do) в транзакции, которая включает выражение и любые вложенные вызовы.

Commute также используется для изменения значения ссылочного типа, как alter и ref-set.

Clojure — Базы данных

Чтобы использовать функциональные возможности базы данных, сначала загрузите файлы jdbc по следующему адресу: https://codeload.github.com/clojure/java.jdbc/zip/master.

Вы найдете zip-файл с драйверами, необходимыми для Clojure, чтобы иметь возможность подключаться к базам данных. После распаковки zip-файла обязательно добавьте разархивированное местоположение в путь к классам.

Основным файлом для подключения к базе данных является файл с именем jdbc.clj в папке clojure / java.

Коннектор clojure jdbc поддерживает широкий спектр баз данных, некоторые из которых перечислены ниже.

  • H2Database
  • оракул
  • Microsoft SQL Server
  • MySQL
  • PostgreSQL

В нашем примере мы будем использовать MySQL DB в качестве примера.

Следующие операции возможны в Clojure в отношении баз данных.

Подключение к базе данных

Перед подключением к базе данных MySQL убедитесь в следующем:

  • Вы создали базу данных TESTDB.

  • Вы создали таблицу EMPLOYEE в TESTDB.

  • В этой таблице есть поля FIRST_NAME, LAST_NAME, AGE, SEX и INCOME.

  • Идентификатор пользователя «testuser» и пароль «test123» установлены для доступа к TESTDB.

  • Убедитесь, что вы загрузили «файл jar mysql» и добавили этот файл в ваш путь к классам.

  • Вы прошли учебник по MySQL, чтобы понять основы MySQL .

Вы создали базу данных TESTDB.

Вы создали таблицу EMPLOYEE в TESTDB.

В этой таблице есть поля FIRST_NAME, LAST_NAME, AGE, SEX и INCOME.

Идентификатор пользователя «testuser» и пароль «test123» установлены для доступа к TESTDB.

Убедитесь, что вы загрузили «файл jar mysql» и добавили этот файл в ваш путь к классам.

Вы прошли учебник по MySQL, чтобы понять основы MySQL .

Синтаксис

Ниже приведен синтаксис для создания соединения в Clojure.

(def connection_name {
   :subprotocol “protocol_name”
   :subname “Location of mysql DB”
   :user “username” :password “password” })

Параметры — «имя_соединения» — это имя, которое будет присвоено соединению. ‘subprotocol’ — это протокол, который будет использоваться для соединения. По умолчанию мы будем использовать протокол mysql. ‘subname’ — это URL для подключения к базе данных mysql вместе с именем базы данных. ‘user’ — это имя пользователя, используемое для подключения к базе данных. «пароль» — это пароль, который будет использоваться для подключения к базе данных.

Возвращаемое значение — это предоставит строку подключения, которая может быть использована в последующих операциях mysql.

В следующем примере показано, как подключиться к таблицам в информационной схеме и извлечь все данные из таблицы.

пример

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/information_schema"
      :user "root"
      :password "shakinstev"})
   (println (sql/query mysql-db
      ["select table_name from tables"]
      :row-fn :table_name)))

Запрос данных

Запрос данных в любой базе данных означает получение некоторой полезной информации из базы данных. Как только соединение с базой данных установлено, вы готовы сделать запрос в эту базу данных. Ниже приводится синтаксис, с помощью которого можно запрашивать данные с помощью Clojure.

Синтаксис

clojure.java.jdbc/query dbconn
["query"]
   :row-fn :sequence

Параметры — ‘dbconn’ — это имя соединения, используемого для подключения к базе данных. ‘query’ — это строка запроса, используемая для извлечения данных из базы данных. ‘: sequence’ — это по умолчанию все строки данных, извлеченные из базы данных, и возвращается как последовательность. Затем можно выполнить необходимые операции над последовательностью, чтобы увидеть, какие данные были выбраны.

Возвращаемое значение — это вернет последовательность, в которой будут строки данных из операции запроса.

В следующем примере показано, как подключиться к таблице сотрудников и извлечь столбец first_name строк в таблице.

пример

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (println (sql/query mysql-db
      ["select first_name from employee"]
      :row-fn :first_name)))

Из приведенного выше кода мы можем видеть, что

  • Запрос «select first_name from employee» передается в виде строки запроса.

  • : First_name — это последовательность, которая возвращается в результате операции выборки.

Запрос «select first_name from employee» передается в виде строки запроса.

: First_name — это последовательность, которая возвращается в результате операции выборки.

Если мы предположим, что в нашей базе данных есть только одна строка, в которой содержится значение first_name, заданное Джоном, то результатом будет вышеприведенная программа.

(John)

Вставка данных

Это необходимо, когда вы хотите создать свои записи в таблице базы данных. Ниже приводится синтаксис, с помощью которого данные могут быть вставлены с использованием Clojure. Это делается с помощью «вставить!» функция.

Синтаксис

clojure.java.jdbc/insert!
   :table_name {:column_namen columnvalue}

Параметры — ‘: table_name’ — это имя таблицы, в которую необходимо произвести вставку. «{: column_namen columnvalue}» — это карта всех имен и значений столбцов, которые необходимо добавить в виде строки в таблице.

Возвращаемое значение — это вернет ноль, если вставка сделана успешно.

В следующем примере показано, как вставить запись в таблицу employee в базе данных testdb.

пример

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (sql/insert! mysql-db
      :employee {:first_name "John" :last_name "Mark" :sex "M" :age 30 :income 30}))

Если вы теперь проверите свою базу данных MySQL и таблицу employee, вы увидите, что приведенная выше строка будет успешно вставлена ​​в таблицу.

Удаление данных

Строки могут быть удалены из таблицы с помощью «Удалить!» функция. Ниже приводится синтаксис того, как эта операция может быть выполнена.

Синтаксис

clojure.java.jdbc/delete!
   :table_name [condition]

Параметры — ‘: table_name’ — это имя таблицы, в которую необходимо произвести вставку. «условие» — это условие, используемое для определения, какую строку необходимо удалить из таблицы.

Возвращаемое значение — это вернет количество удаленных строк.

В следующем примере показано, как удалить запись из таблицы employee в базе данных testdb. В примере удаляется строка из таблицы на основе условия, что возраст равен 30.

пример

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (println (sql/delete! mysql-db
      :employee ["age = ? " 30])))

Если у вас была запись, в которой строка с возрастом равным 30, эта строка будет удалена.

Обновление данных

Строки могут быть обновлены из таблицы с помощью «обновления!» функция. Ниже приводится синтаксис того, как эта операция может быть выполнена.

Синтаксис

clojure.java.jdbc/update!
   :table_name
{setcondition}
[condition]

Параметры — ‘: table_name’ — это имя таблицы, в которую необходимо произвести вставку. ‘setcondition’ — это столбец, который необходимо обновить, как указано в терминах карты. «условие» — это условие, которое используется для определения, какую строку необходимо удалить из таблицы.

Возвращаемое значение — это вернет количество обновленных строк.

В следующем примере показано, как удалить запись из таблицы employee в базе данных testdb. В примере обновляется строка из таблицы на основе условия, что возраст равен 30, и обновляется значение дохода до 40.

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (println (sql/update! mysql-db
      :employee
      {:income 40}
      ["age = ? " 30])))

Если у вас есть запись, в которой строка с возрастом, равным значению 30, будет обновлена, в ней значение дохода будет равно 40.

операции

Транзакции — это механизмы, обеспечивающие согласованность данных. Транзакции имеют следующие четыре свойства —

  • Атомарность — либо транзакция завершена, либо ничего не происходит вообще.

  • Согласованность — транзакция должна начинаться в согласованном состоянии и оставлять систему в согласованном состоянии.

  • Изоляция — промежуточные результаты транзакции не видны за пределами текущей транзакции.

  • Долговечность — после совершения транзакции последствия сохраняются даже после сбоя системы.

Атомарность — либо транзакция завершена, либо ничего не происходит вообще.

Согласованность — транзакция должна начинаться в согласованном состоянии и оставлять систему в согласованном состоянии.

Изоляция — промежуточные результаты транзакции не видны за пределами текущей транзакции.

Долговечность — после совершения транзакции последствия сохраняются даже после сбоя системы.

пример

В следующем примере показано, как реализовать транзакции в Clojure. Любые операции, которые необходимо выполнить в транзакции, должны быть встроены в предложение with-dbtransaction .

(ns test.core
   (:require [clojure.java.jdbc :as sql]))
(defn -main []
   (def mysql-db {
      :subprotocol "mysql"
      :subname "//127.0.0.1:3306/testdb"
      :user "root"
      :password "shakinstev"})
   (sql/with-db-transaction [t-con mysql-db]
      (sql/update! t-con
         :employee
         {:income 40}
         ["age = ? " 30])))

Clojure — интерфейс Java

Как мы уже знаем, код Clojure работает в виртуальной среде Java в конце. Таким образом, имеет смысл только то, что Clojure может использовать все функциональные возможности Java. В этой главе давайте обсудим корреляцию между Clojure и Java.

Вызов методов Java

Методы Java могут быть вызваны с использованием точечной нотации. Примером являются строки. Поскольку все строки в Clojure в любом случае являются строками Java, вы можете вызывать обычные методы Java для строк.

Пример того, как это делается, показан в следующей программе.

пример

Live Demo

(ns Project
   (:gen-class))
(defn Example []
   (println (.toUpperCase "Hello World")))
(Example)

Вышеуказанная программа производит следующий вывод. Из кода видно, что если вы просто вызовете точечную запись для любого строкового метода, он также будет работать в Clojure.

Выход

HELLO WORLD

Вызов методов Java с параметрами

Вы также можете вызывать методы Java с параметрами. Пример того, как это делается, показан в следующей программе.

пример

Live Demo

(ns Project
   (:gen-class))
(defn Example []
   (println (.indexOf "Hello World","e")))
(Example)

Вышеуказанная программа производит следующий вывод. Из приведенного выше кода видно, что мы передаем параметр «e» в метод indexOf. Вышеуказанная программа производит следующий вывод.

Выход

1

Создание объектов Java

Объекты могут быть созданы в Clojure с помощью ключевого слова «new», аналогичного тому, что делается в Java.

Пример того, как это делается, показан в следующей программе.

пример

Live Demo

(ns Project
   (:gen-class))
(defn Example []
   (def str1 (new String "Hello"))
   (println str1))
(Example)

Вышеуказанная программа производит следующий вывод. Из приведенного выше кода видно, что мы можем использовать ключевое слово «new» для создания нового объекта из существующего класса String из Java. Мы можем передать значение при создании объекта, как в Java. Вышеуказанная программа производит следующий вывод.

Выход

Hello

Ниже приведен еще один пример, который показывает, как мы можем создать объект класса Integer и использовать их в обычных командах Clojure.

пример

Live Demo

(ns Project
   (:gen-class))
(defn Example []
   (def my-int(new Integer 1))
   (println (+ 2 my-int)))
(Example)

Вышеуказанная программа производит следующий вывод.

Выход

3

Команда импорта

Мы также можем использовать команду import для включения библиотек Java в пространство имен, чтобы к классам и методам можно было легко получить доступ.

В следующем примере показано, как мы можем использовать команду импорта. В этом примере мы используем команду import для импорта классов из библиотеки java.util.stack . Затем мы можем использовать метод push и pop класса стека как есть.

пример

Live Demo

(ns Project
   (:gen-class))
(import java.util.Stack)
(defn Example []
   (let [stack (Stack.)]
   (.push stack "First Element")
   (.push stack "Second Element")
   (println (first stack))))
(Example)

Вышеуказанная программа производит следующий вывод.

Выход

First Element

Выполнение кода с помощью команды Java

Код Clojure можно запустить с помощью команды Java. Ниже приводится синтаксис того, как это можно сделать.

java -jar clojure-1.2.0.jar -i main.clj

Вы должны упомянуть файл jar Clojure, чтобы все классы, основанные на Clojure, были загружены в JVM. Файл main.clj — это файл кода Clojure, который необходимо выполнить.

Встроенные функции Java

Clojure может использовать многие встроенные функции Java. Некоторые из них —

Математическая функция PI — Clojure может использовать метод Math для значения PI. Ниже приведен пример кода.

пример

Live Demo

(ns Project
   (:gen-class))
(defn Example []
   (println (. Math PI)))
(Example)

Приведенный выше код производит следующий вывод.

Выход

3.141592653589793

Системные свойства — Clojure также может запрашивать системные свойства. Ниже приведен пример кода.

пример

Live Demo

(ns Project
   (:gen-class))
(defn Example []
   (println (.. System getProperties (get "java.version"))))
(Example)

В зависимости от версии Java в системе будет отображаться соответствующее значение. Ниже приведен пример вывода.

Выход

1.8.0_45

Clojure — параллельное программирование

В программировании Clojure большинство типов данных являются неизменяемыми, поэтому, когда речь идет о параллельном программировании, код, использующий эти типы данных, довольно безопасен, когда код выполняется на нескольких процессорах. Но часто требуется совместное использование данных, и когда дело доходит до обмена данными между несколькими процессорами, возникает необходимость обеспечить сохранение состояния данных с точки зрения целостности при работе с несколькими процессорами. Это известно как параллельное программирование, и Clojure обеспечивает поддержку такого программирования.

Программная система транзакционной памяти (STM), предоставляемая посредством dosync, ref, set, alter и т. Д., Поддерживает совместное использование изменяющегося состояния между потоками синхронным и скоординированным образом. Система агентов поддерживает совместное использование изменяющегося состояния между потоками асинхронным и независимым способом. Система атомов поддерживает разделение изменяющегося состояния между потоками синхронно и независимо. Принимая во внимание, что динамическая система var, доступная через def, привязку и т. Д., Поддерживает изоляцию изменяющегося состояния внутри потоков.

Другие языки программирования также следуют модели параллельного программирования.

  • Они имеют прямую ссылку на данные, которые могут быть изменены.

  • Если требуется общий доступ, объект блокируется, значение изменяется, и процесс продолжается для следующего доступа к этому значению.

Они имеют прямую ссылку на данные, которые могут быть изменены.

Если требуется общий доступ, объект блокируется, значение изменяется, и процесс продолжается для следующего доступа к этому значению.

В Clojure нет блокировок, но есть косвенные ссылки на неизменяемые постоянные структуры данных.

В Clojure есть три типа ссылок.

  • Изменения — изменения изолированы в потоках.

  • Refs — Изменения синхронизируются и координируются между потоками.

  • Агенты — включает асинхронные независимые изменения между потоками.

Изменения — изменения изолированы в потоках.

Refs — Изменения синхронизируются и координируются между потоками.

Агенты — включает асинхронные независимые изменения между потоками.

Следующие операции возможны в Clojure в отношении параллельного программирования.

операции

Параллелизм в Clojure основан на транзакциях. Ссылки могут быть изменены только внутри транзакции. Следующие правила применяются в транзакциях.

  • Все изменения являются атомарными и изолированными.
  • Каждое изменение ссылки происходит в транзакции.
  • Ни одна транзакция не видит эффект от другой транзакции.
  • Все транзакции размещаются внутри блока dosync.

Мы уже видели, что делает блок dosync, давайте посмотрим на него еще раз.

dosync

Запускает выражение (в неявном do) в транзакции, которая включает выражение и любые вложенные вызовы. Запускает транзакцию, если в этом потоке еще не запущено ни одного. Любое необработанное исключение прервет транзакцию и выйдет из режима досинхронизации.

Ниже приводится синтаксис.

Синтаксис

(dosync expression)

Параметры — ‘expression’ — это набор выражений, которые будут входить в блок dosync.

Возвращаемое значение — Нет.

Давайте рассмотрим пример, в котором мы пытаемся изменить значение ссылочной переменной.

пример

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def names (ref []))
   (alter names conj "Mark"))
(Example)

Выход

Приведенная выше программа при запуске выдает следующую ошибку.

Caused by: java.lang.IllegalStateException: No transaction running
   at clojure.lang.LockingTransaction.getEx(LockingTransaction.java:208)
   at clojure.lang.Ref.alter(Ref.java:173)
   at clojure.core$alter.doInvoke(core.clj:1866)
   at clojure.lang.RestFn.invoke(RestFn.java:443)
   at clojure.examples.example$Example.invoke(main.clj:5)
   at clojure.examples.example$eval8.invoke(main.clj:7)
   at clojure.lang.Compiler.eval(Compiler.java:5424)
   ... 12 more

Из ошибки ясно видно, что вы не можете изменить значение ссылочного типа без предварительной инициации транзакции.

Чтобы приведенный выше код работал, мы должны поместить команду alter в блок dosync, как это сделано в следующей программе.

пример

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def names (ref []))
   
   (defn change [newname]
      (dosync
         (alter names conj newname)))
   (change "John")
   (change "Mark")
   (println @names))
(Example)

Вышеуказанная программа производит следующий вывод.

Выход

[John Mark]

Давайте посмотрим еще один пример dosync.

пример

Live Demo

(ns clojure.examples.example
   (:gen-class))
(defn Example []
   (def var1 (ref 10))
   (def var2 (ref 20))
   (println @var1 @var2)
   
   (defn change-value [var1 var2 newvalue]
      (dosync
         (alter var1 - newvalue)
         (alter var2 + newvalue)))
   (change-value var1 var2 20)
   (println @var1 @var2))
(Example)

В приведенном выше примере у нас есть два значения, которые изменяются в блоке DOSINC. Если транзакция успешна, оба значения изменятся, иначе вся транзакция не удастся.

Вышеуказанная программа производит следующий вывод.

Выход

10 20
-10 40

Clojure — Приложения

В Clojure есть несколько библиотек, которые позволяют создавать приложения для рабочего стола и веб-приложения . Давайте обсудим каждый из них.

Sr.No. Приложения и описание
1 Рабочий стол — Качели

See-saw — это библиотека, которую можно использовать для создания настольных приложений.

2 Рабочий стол — изменение значения текста

Значение содержимого в окне может быть изменено с помощью «config!» вариант. В следующем примере конфиг! опция используется для изменения содержимого окна на новое значение «До свидания».

3 Рабочий стол — отображение модального диалогового окна

Модальное диалоговое окно может быть показано с помощью метода alert класса see-saw. Метод принимает текстовое значение, которое необходимо отобразить в модальном диалоговом окне.

4 Рабочий стол — отображение кнопок

Кнопки могут отображаться с помощью класса кнопок.

5 Рабочий стол — отображение меток

Ярлыки могут отображаться с помощью класса ярлыков.

6 Рабочий стол — Отображение текстовых полей

Текстовые поля могут быть отображены с помощью текстового класса.

See-saw — это библиотека, которую можно использовать для создания настольных приложений.

Значение содержимого в окне может быть изменено с помощью «config!» вариант. В следующем примере конфиг! опция используется для изменения содержимого окна на новое значение «До свидания».

Модальное диалоговое окно может быть показано с помощью метода alert класса see-saw. Метод принимает текстовое значение, которое необходимо отобразить в модальном диалоговом окне.

Кнопки могут отображаться с помощью класса кнопок.

Ярлыки могут отображаться с помощью класса ярлыков.

Текстовые поля могут быть отображены с помощью текстового класса.

Веб-приложения — Введение

Для создания веб-приложения в Clojure необходимо использовать библиотеку приложений Ring, которая доступна по следующей ссылке https://github.com/ring-clojure/ring.

Вам необходимо убедиться, что вы загрузили необходимые jar-файлы с сайта и добавили их в качестве зависимости для приложения Clojure.

Платформа Ring предоставляет следующие возможности:

  • Настраивает все так, чтобы запрос http поступал в ваше веб-приложение в виде обычного Clojure HashMap, а также настраивал его так, чтобы вы могли возвращать ответ в виде HashMap.

  • Предоставляет спецификацию, описывающую, как именно должны выглядеть эти карты запросов и ответов.

  • Создает веб-сервер (Jetty) и подключает к нему ваше веб-приложение.

Настраивает все так, чтобы запрос http поступал в ваше веб-приложение в виде обычного Clojure HashMap, а также настраивал его так, чтобы вы могли возвращать ответ в виде HashMap.

Предоставляет спецификацию, описывающую, как именно должны выглядеть эти карты запросов и ответов.

Создает веб-сервер (Jetty) и подключает к нему ваше веб-приложение.

Платформа Ring автоматически запускает веб-сервер и обеспечивает работу приложения Clojure на этом сервере. Тогда можно также использовать платформу Compojure. Это позволяет создавать маршруты, как в настоящее время разрабатывается большинство современных веб-приложений.

Создание первого приложения Clojure. В следующем примере показано, как создать первое веб-приложение в Clojure.

(ns my-webapp.handler
   (:require [compojure.core :refer :all]
      [compojure.route :as route]
      [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
   (GET "/" [] "Hello World")
   (route/not-found "Not Found"))
(def app
   (wrap-defaults app-routes site-defaults))

Давайте посмотрим на следующие аспекты программы —

  • ‘Defroutes’ используется для создания маршрутов, так что запросы к веб-приложению на разные маршруты могут быть направлены на разные функции в вашем приложении Clojure.

  • В приведенном выше примере символ «/» известен как маршрут по умолчанию, поэтому при переходе к базе веб-приложения строка «Hello World» будет отправлена ​​в веб-браузер.

  • Если пользователь нажмет любой URL-адрес, который не может быть обработан приложением Clojure, он отобразит строку «Not Found».

‘Defroutes’ используется для создания маршрутов, так что запросы к веб-приложению на разные маршруты могут быть направлены на разные функции в вашем приложении Clojure.

В приведенном выше примере символ «/» известен как маршрут по умолчанию, поэтому при переходе к базе веб-приложения строка «Hello World» будет отправлена ​​в веб-браузер.

Если пользователь нажмет любой URL-адрес, который не может быть обработан приложением Clojure, он отобразит строку «Not Found».

Когда вы запускаете приложение Clojure, по умолчанию ваше приложение будет загружаться как localhost: 3000, поэтому, если вы перейдете в это местоположение, вы получите следующий вывод.

Clojure Применение

Веб-приложения — добавление большего количества маршрутов в ваше веб-приложение

Вы также можете добавить больше маршрутов в ваше веб-приложение. В следующем примере показано, как этого добиться.

(ns my-webapp.handler
   (:require [compojure.core :refer :all]
      [compojure.route :as route]
      [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
   (GET "/" [] "Hello World")
   (GET "/Tutorial" [] "This is a tutorial on Clojure")
   (route/not-found "Not Found"))
(def app
   (wrap-defaults app-routes site-defaults))

Вы можете видеть, что добавить маршрут в приложение так же просто, как просто добавить еще одну функцию GET с помощью URL-маршрута. (GET «/ Tutorial» [] «Это учебник по Clojure»)

Если вы перейдете по адресу http: // localhost: 3000 / Tutorial , вы получите следующий вывод.

Localhost

Clojure — автоматическое тестирование

В этой главе давайте обсудим варианты автоматического тестирования, предоставляемые Clojure.

Тестирование для клиентских приложений

Чтобы использовать тестирование для среды Clojure, вы должны использовать зависимости, расположенные по адресу https://github.com/slagyr/speclj#manual-installation.

Этот URL-адрес предоставляет платформу speclj , которая используется в качестве тестовой среды, управляемой данными или поведением, для платформы Clojure. Вы должны убедиться, что используете каркас Clojure 1.7.0 при использовании любой из библиотек ‘speclj’. По умолчанию тестовые файлы будут отличаться от файлов кода Clojure и должны быть помещены в каталог spec.

Ниже приведен пример кода для тестового файла.

(ns change.core-spec
   (:require [speclj.core :refer :all]))
(describe "Truth"
   (it "is true"
   (should true))
   (it "is not false"
   (should-not false)))
(run-specs)

В отношении приведенного выше кода необходимо отметить следующее:

  • Сначала мы должны убедиться, что используется оператор require для включения всех базовых библиотек в инфраструктуру speclj.

  • Далее идет функция «описать». Это используется для предоставления описания создаваемого тестового примера.

  • Следующая функция — это функция ‘it’, которая является реальным тестовым примером. В первом тестовом примере строка «истина» — это имя, данное тестовому примеру.

  • Должны и не должны называться утверждениями . Все утверждения должны начинаться с Должны и не должны быть только два из многих доступных утверждений. Они оба принимают выражения, которые они будут проверять на правдивость и ложность соответственно.

Сначала мы должны убедиться, что используется оператор require для включения всех базовых библиотек в инфраструктуру speclj.

Далее идет функция «описать». Это используется для предоставления описания создаваемого тестового примера.

Следующая функция — это функция ‘it’, которая является реальным тестовым примером. В первом тестовом примере строка «истина» — это имя, данное тестовому примеру.

Должны и не должны называться утверждениями . Все утверждения должны начинаться с Должны и не должны быть только два из многих доступных утверждений. Они оба принимают выражения, которые они будут проверять на правдивость и ложность соответственно.

Если вы запустите тестовый пример, вы получите следующий вывод. Выходные данные показывают время, необходимое в миллисекундах для запуска тестового примера.

←[32m.←[0m←[32m.←[0m
Finished in 0.00014 seconds

Тестирование для веб-приложений

Selenium является одной из ключевых сред, используемых для тестирования современных веб-приложений. Также доступны библиотеки Clojure, которые можно использовать для тестирования веб-приложений.

Давайте посмотрим, как мы можем использовать библиотеки Selenium для тестирования веб-приложений Clojure.

Шаг 1. Первый шаг — убедиться, что мы используем инфраструктуру Ring и Compojure для создания веб-приложения, которое необходимо протестировать. Давайте использовать один из примеров из наших предыдущих глав. Следующий код представляет собой простое веб-приложение, которое отображает «Hello World» в браузере.

(ns my-webapp.handler
   (:require [compojure.core :refer :all]
      [compojure.route :as route]
      [ring.middleware.defaults :refer [wrap-defaults site-defaults]]))
(defroutes app-routes
   (GET "/" [] "Hello World")
   (route/not-found "Not Found"))
(def app
   (wrap-defaults app-routes site-defaults))

Шаг 2 — Затем обязательно загрузите файл jar селена https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-server/2.47.0 и включите его в путь к классам.

Шаг 3 — Также убедитесь, что вы скачали веб-драйвер ‘clj’, который будет использоваться для запуска веб-теста, из следующей папки.

https://clojars.org/clj-webdriver/versions/0.7.1

Шаг 4 — Создайте в каталоге вашего проекта еще один каталог с функциями и создайте файл с именем «config.clj».

Шаг 5 — Затем добавьте следующий код в файл config.clj, созданный на предыдущем шаге.

ns clj-webdriver-tutorial.features.config)
(def test-port 3000)
(def test-host "localhost")
(def test-base-url (str "http://" test-host ":" test-port "/"))

Приведенный выше код в основном сообщает инфраструктуре веб-тестирования для тестирования приложения, которое загружается по URL-адресу http: // localhost: 3000

Шаг 6 — Наконец, давайте напишем наш код для проведения нашего теста.

(ns clj-webdriver-tutorial.features.homepage
   (:require [clojure.test :refer :all]
      [ring.adapter.jetty :refer [run-jetty]]
      [clj-webdriver.taxi :refer :all]
      [clj-webdriver-tutorial.features.config :refer :all]
      [clj-webdriver-tutorial.handler :refer [app-routes]]))
(ns clj-webdriver-tutorial.features.homepage
   (:require [clojure.test :refer :all]
      [ring.adapter.jetty :refer [run-jetty]]
      [clj-webdriver.taxi :refer :all]
      [clj-webdriver-tutorial.features.config :refer :all]
      [clj-webdriver-tutorial.handler :refer [app-routes]]))
(defn start-server []
   (loop [server (run-jetty app-routes {:port test-port, :join? false})]
      (if (.isStarted server)
         server
         (recur server))))
(defn stop-server [server]
   (.stop server))
(defn start-browser []
   (set-driver! {:browser :firefox}))
(defn stop-browser []
   (quit))
(deftest homepage-greeting
   (let [server (start-server)]
      (start-browser)
      (to test-base-url)
      (is (= (text "body") "Hello World"))
      (stop-browser)
      (stop-server server)))

Приведенный выше код собирается предпринять следующие действия —

  • Запустите сервер для приложения.
  • Откройте корневой путь в браузере.
  • Проверьте, присутствует ли на странице сообщение «Hello World».
  • Закройте браузер.
  • Завершите работу сервера.

Clojure — Библиотеки

Одна вещь, которая делает библиотеку Clojure такой мощной, — это количество библиотек, доступных для платформы Clojure. Мы уже видели так много библиотек, которые использовались в наших предыдущих примерах для веб-тестирования, веб-разработки, разработки основанных на свинге приложений, библиотеки jdbc для подключения к базам данных MySQL. Ниже приведены лишь несколько примеров нескольких библиотек.

data.xml

Эта библиотека позволяет Clojure работать с данными XML. Используемая версия библиотеки: org.clojure / data.xml «0.0.8». Data.xml поддерживает синтаксический анализ и передачу XML. Функции синтаксического анализа будут читать XML из Reader или InputStream.

пример

Ниже приведен пример обработки данных из строки в XML.

(ns clojure.examples.example
   (use 'clojure.data.xml)
   (:gen-class))
(defn Example []
   (let [input-xml (java.io.StringReader. "<?xml version = \"1.0\"
      encoding = \"UTF-8\"?><example><clo><Tutorial>The Tutorial
      value</Tutorial></clo></example>")]
      (parse input-xml)))

#clojure.data.xml.Element{
   :tag :example, :attrs {}, :content (#clojure.data.xml.Element {
      :tag :clo, :attrs {}, :content (#clojure.data.xml.Element {
         :tag :Tutorial, :attrs {},:content ("The Tutorial value")})})}
(Example)

data.json

Эта библиотека позволяет Clojure работать с данными JSON. Используемая версия библиотеки — org.clojure / data.json «0.2.6».

пример

Ниже приведен пример использования этой библиотеки.

Live Demo

(ns clojure.examples.example
   (:require [clojure.data.json :as json])
   (:gen-class))
(defn Example []
   (println (json/write-str {:a 1 :b 2})))
(Example)

Выход

Вышеуказанная программа производит следующий вывод.

{\"a\":1,\"b\":2}

data.csv

Эта библиотека позволяет Clojure работать с данными ‘csv’ . Используемая версия библиотеки — org.clojure / data.csv «0.1.3».

пример

Ниже приведен пример использования этой библиотеки.

(ns clojure.examples.example
   (require '[clojure.data.csv :as csv]
      '[clojure.java.io :as io])
   (:gen-class))
(defn Example []
   (with-open [in-file (io/reader "in-file.csv")]
      (doall
      (csv/read-csv in-file)))
   (with-open [out-file (io/writer "out-file.csv")]
   (csv/write-csv out-file
      [[":A" "a"]
      [":B" "b"]])))
(Example)

В приведенном выше коде функция ‘csv’ сначала прочитает файл in-file.csv и поместит все данные в переменную in-file. Далее мы используем функцию write-csv для записи всех данных в файл с именем out-file.csv.