Основні типи даних
Мова ClojureScript, як і більшість мов програмування має багатий набір типів даних. Вона має добре відомі вам скалярні типи даних, такі як числа, рядки та числа з рухомою крапкою. Також, в ній є багато інших, з якими ви можете бути незнайомі, такі як символи, ключові слова, регекспи (регулярні вирази), змінні, атоми та волатайли (volatile).
ClojureScript використовує типи даних батьківської платформи, коли це можливо. Наприклад: числа та рядки використовуються і поводяться так само, як і в JavaScript.
Числа
В ClojureScript числа включають в себе цілі числа та числа з рухомою крапкою. Враховуючи те, що ClojureScript це гостьова мова, що компілюється в JavaScript, під капотом цілі числа насправді є числами з рухомою крапкою в JavaScript.
Як і в багатьох інших мовах, в ClojureScript числа представлені в наступних форматах:
23
+23
-100
1.7
-2
33e8
12e-14
3.2e-4
Ключові слова
В ClojureScript ключові слова — це тип даних, в якому значення означають нічого іншого крім самих себе. Вони використовуються, як ключі в мапах для ефективного доступу до значень.
:foobar
:2
:?
:foo/bar
Як ви можете бачити, ключові слова починаються зі знаку :
, але цей знак не є частиною імені об'єкту — він лише частина синтаксису літералу ключового слова.
Також ключове слово можна створити, викликавши функцію keyword
. Не турбуйтесь, якщо ви нічого не зрозумієте в наступному прикладі; функції будуть розглянуті пізніше.
(keyword "foo")
;; => :foo
Символи
В ClojureScript символи дуже схожі на ключові слова (про які ви тепер знаєте). Але замість того, щоб означати тільки самих себе, символи означають те, на що вони посилаються: функція, значення, тощо.
Символи не можуть починатися цифрою, але можуть мати алфавітно-цифрові літери, а також знаки *
, +
, !
, -
, _
, '
, і ?
, наприклад:
sample-symbol
othersymbol
f1
my-special-swap!
Не хвилюйтесь якщо ви не розумієте цього зараз; символи використовуються практично у всіх наших прикладах, що дозволяє вам вивчити більше по ходу.
Рядки
Ми не розкажемо нічого нового, чого ви можете не знати про рядки. В ClojureScript вони працюють так само, як і в будь-якій іншій мові. Цікаво лише те, що вони незмінні.
Вони такі ж самі, як і в JavaScript:
"An example of a string"
Але, завдяки синтаксису Lisp, особливим аспектом рядків у ClojureScript є те, що одно- та багаторядкові рядки мають той самий синтаксис:
"This is a multiline
string in ClojureScript."
Літери
ClojureScript також дозволяє писати окремі літери, використовуючи синтаксис літерала з Clojure.
\a ; The lowercase a character
\newline ; The newline character
Оскільки батьківська мова не має синтаксису для літералу літери, в ClojureScript літери представлені як рядки з JavaScript з однією літерою.
Колекції
Ще одним значним кроком у поясненні мови — є пояснення її колекцій та абстракцій колекції. ClojureScript не є винятком.
В ClojureScript є багато типів колекцій. Головною відмінністю колекцій в ClojureScript від колекцій в інших мовах є те, що вони стійкі (persistent) та незмінні.
Перед тим, як перейти до цих (можливо) невідомих понять, ми розглянемо існуючі типи колекцій в ClojureScript.
Списки
Це класичний тип колекції в мовах родини Lisp. В ClojureScript списки — найпростіший тип колекції. Списки можуть містити елементи будь-якого типу, включаючи інші колекції.
В ClojureScript списки представлені як ряд значень у круглих дужках:
'(1 2 3 4 5)
'(:foo :bar 2)
Як ви можете бачити, приклади списків мають префікс '
. Це тому, що в мовах родини Lisp списки часто використовуються для вираження виклику функції чи макросу. В такому випадку, першим елементом повинен бути символ, що означає щось, що можна викликати (функцію), а решта елементів будуть аргументами цієї функції. Однак, у цьому прикладі ми не хочемо, щоб перший елемент був символом; ми хочемо список елементів.
Наступний приклад показує відмінність списку без та з одинарними лапками:
(inc 1)
;; => 2
'(inc 1)
;; => (inc 1)
Як ви можете побачити, якщо ви виконаєте (inc 1)
без префіксу '
, символ inc
стане функцією, що буде викликана з аргументом 1
і поверне результат 2
.
Список можна створити явно за допомогою функції list
:
(list 1 2 3 4 5)
;; => (1 2 3 4 5)
(list :foo :bar 2)
;; => (:foo :bar 2)
Списки особливі тим, що доступ до першого елементу та послідовний доступ до наступних є дуже ефективним, але вони не будуть вдалим вибором, коли вам потрібен випадковий (по індексу) доступ до елементів.
Вектори
Так само, як і списки, вектори містять ряд значень, але в цьому випадку, вони мають дуже ефективний доступ по індексу, на відміну від списків, які обчислюються поступово. Не турбуйтесь; в наступних частинах ми розглянемо це більш детально, але зараз простого пояснення буде більш ніж достатньо.
Вектори використовують квадратні дужки в синтаксисі літералу; давайте розглянемо кілька прикладів:
[:foo :bar]
[3 4 5 nil]
Як і списки, вектори можуть містити об’єкти будь-якого типу, що видно з попереднього прикладу.
Вектор також можна створити за допомогою функції vector
, але, зазвичай, це не використовується:
(vector 1 2 3)
;; => [1 2 3]
(vector "blah" 3.5 nil)
;; => ["blah" 3.5 nil]
Мапи
Мапа — це абстракція колекції, що дозволяє зберігати дані у вигляді пар ключ-значення. В інших мовах цей тип даних часто відомий як хеш-мапа або dict (словник). Літерал мапи в ClojureScript записується парами ключ-значення між фігурними дужками.
{:foo "bar", :baz 2}
{:alphabet [:a :b :c]}
Примітка.
Коми часто використовуються для поділу пар ключ-значення, але це не є обов’язковим. У синтаксисі ClojureScript, коми — це пробіли.
Як і в векторах, кожен елемент в літералі мапи обчислюється перед збереженням у саму мапу, але порядок обчислення та збереження не гарантується.
Множини
І нарешті, множини.
Множина — це невпорядкований ряд унікальних елементів будь-якого типу. Як і в мапах, літерал множини має фігурні дужки, але перед ними додається знак #
. Можна також використовувати функцію set
для конвертування колекцій у множини:
#{1 2 3 :foo :bar}
;; => #{1 :bar 3 :foo 2}
(set [1 2 1 3 1 4 1 5])
;; => #{1 2 3 4 5}
У наступних розділах ми розглянемо множини та інші типи колекцій більш детально.