Ключевые слова и символы
Разбираемся в двух похожих, но разных сущностях Clojure: символах и ключевых словах.
Символ — имя, которое что-то обозначает (функцию, переменную). Ключевое слово — самоозначающая константа, которая обозначает саму себя.
Символы: имена для вещей
Символ — это просто имя, например x, + или println. Когда компилятор видит символ в позиции для вычисления, он ищет, на что тот указывает (значение переменной или функцию). Символы — то, чем вы называете определения через def и defn.
(def цена 100)
; цена - символ, указывающий на число 100
цена ; => 100Ключевые слова: константы, означающие себя
Ключевое слово начинается с двоеточия: :name, :age, :status. В отличие от символа, оно не ищет никакого значения — оно есть своё значение. :age всегда равно :age, как число 5 всегда равно 5.
:status ; => :status
(= :a :a) ; => true
(keyword "x") ; => :x (строку можно превратить в keyword)Вывод:
:status true :x
Зачем нужны ключевые слова
Главное применение — ключи в отображениях (map). Ключевые слова идеально подходят на роль имён полей: они быстрые, читаемые и сами умеют доставать значение из map.
(def пользователь {:имя "Аня" :возраст 30})
; keyword можно вызвать КАК ФУНКЦИЮ от map:
(:имя пользователь) ; => "Аня"
(:возраст пользователь) ; => 30
; И наоборот, map работает как функция от ключа:
(пользователь :имя) ; => "Аня"Вывод:
"Аня" 30 "Аня"
Как работает под капотом
Ключевые слова интернируются: одинаковые :age в разных местах программы — это один и тот же объект в памяти. Поэтому сравнение двух keyword мгновенно (сравниваются ссылки, а не символы строки). Это делает их идеальными ключами в хэш-отображениях. Символы же при вычислении проходят разрешение (resolution) — поиск того, на что они указывают в текущем пространстве имён.
Символ против ключевого слова: памятка
| Символ | Ключевое слово | |
| Запись | name | :name |
| Что значит | указывает на что-то | означает само себя |
| При вычислении | ищет значение | возвращает себя |
| Типичная роль | имена def/defn, функции | ключи в map, метки |
Частые ошибки
- Путать
:nameиname. Первое — константа-метка, второе — имя, которое будет вычислено. - Использовать строки вместо keyword в map. Строки работают, но keyword быстрее, короче и удобнее как функции.
- Ставить двоеточие в конце. Ключевое слово начинается с двоеточия:
:age, а неage:.
Итоги
- Символ — имя, указывающее на значение; при вычислении разрешается.
- Ключевое слово (с двоеточия) означает само себя и интернируется.
- Keyword — стандартные ключи в map; их можно вызывать как функцию от map.
- Интернирование делает сравнение и поиск по keyword очень быстрыми.