Clojure — не является полностью функциональным языком программирования (Haskell, например, является), однако, это в большей степени продиктовано прагматичностью, которая заложена в дизайне языка. Благодаря этому, в Clojure можно оперировать как константами, так и переменными. Для начала, рассмотрим константы (создаются с помощью формы def
):
(def id expr)
; id — идентификатор
; expr — выражение
; форма def 'связывает' идентификатор с выражением
(def lang "clojure")
(println lang) ; => clojure
Значением объявления может быть как нормальная форма (значение), так и составная:
(def result (+ 7 (- 4 6)))
(println result) ; => 5
def
связывает имя (идентификатор) и значение следующего за ним выражения в рамках пространства имен
, в котором происходит объявление. Имена объявлений, состоящие из нескольких слов, соединяют с помощью дефиса. В Lisp-языках повсеместно принят так называемый "kebab-case".
(def dangerous-year 1984)
(println dangerous-year) ; => 1984
Если же нужно работать с каким-либо изменяемым состоянием, тогда на помощь приходит форма atom
с набором функций, благодаря которым атом
можно менять:
(def lang (atom "clojure"))
(println @lang) ; => clojure
; мутируем lang
(reset! lang "Clojure!!!")
(println @lang) ; => "Clojure!!!
; объявим счетчик
(def counter (atom 0))
; поменяем его с помощью форм swap! и inc
(swap! counter inc) ; => 1
(swap! counter inc) ; => 2
; а теперь уменьшим счетчик на 1
(swap! counter dec) ; => 1
В общем случае использовать атомы как переменные не рекомендуется. Clojure отлично поддерживает функциональную парадигму и всячески её поощряет. Код с переменными практически всегда легко заменяется на код с константами. Как было описано выше, тема атомов и изменяемого состояния будет рассмотрена позже в соответствующем модуле.
Заметим, что в данном случае мы тоже использовали форму def
, почему так? Идея связывания (от англ. binding) является идиоматическим способом записать функцию, в которую передается аргументом то, что записано в связывании
. Звучит немного запутанно, поэтому еще раз рассмотрим пример выше поподробнее:
(def ; используем форму def
lang ; lang является идентификатором, с которым происходит связывание
(atom ; атом здесь является выражением, которое возвращает ссылку
"clojure" ; данные, на которые ссылается атом
)
)
Благодаря тому, что связывание является более верхоуровневой концепцией, чем ссылка, мы можем связывать идентификатор не только с данными или ссылками, но и с функциями (функции будут рассмотрены дальше, не страшно, если что-то в примере ниже не будет до конца понятно).
(def my-fn (fn [a] (inc a))) ; => свяжем идентификатор my-fn с анонимной функцией, в которой переданный аргумент увеличивается на 1
(my-fn 1) ; => 2
(my-fn 8) ; => 9
Создайте объявление, обозначающее "количество участников" (имя соорудите сами), присвойте ему значение 10 и распечатайте на экран.
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Ваше упражнение проверяется по этим тестам
1(ns define-test
2 (:require [test-helper :refer [assert-output]]))
3
4(assert-output "10")
5
Решение учителя откроется через: