Из комментария к другому вопросу, кто-то говорит, что Clojure idiom предпочитает возвращать нуль, а не пустой список, как на Схеме. Почему это?
Как
(when (seq lat) ...)
вместо
(if (empty? lat)
'() ...)
Из комментария к другому вопросу, кто-то говорит, что Clojure idiom предпочитает возвращать нуль, а не пустой список, как на Схеме. Почему это?
Как
(when (seq lat) ...)
вместо
(if (empty? lat)
'() ...)
Я могу думать о нескольких причинах:
Логическое различие. В Clojure nil означает ничего/отсутствие значения. Принимая во внимание, что "()" пустой список - это значение, это просто значение, которое является пустым списком. Это довольно часто концептуально и логически полезно для различения двух.
Fit with JVM - объектная модель JVM поддерживает нулевые ссылки. И довольно много API Java возвращают значение null, что означает "ничего" или "значение не найдено". Поэтому для обеспечения удобной совместимости с JVM имеет смысл использовать Clojure для использования nil аналогичным образом.
Лень - логика здесь довольно сложная, но я понимаю, что использование nil для "нет списка" лучше работает с Clojure ленивые последовательности. Поскольку Clojure является ленивым функциональным языком программирования по умолчанию, для этого использования имеет смысл быть стандартным. Подробнее см. http://clojure.org/lazy.
"Фальшивость" . Удобно использовать nil для обозначения "ничего", а также "false" при написании условного кода, который исследует коллекции, поэтому вы можете написать код типа (if (some-map :some-key) ....)
проверить, содержит ли хэш-карта значение для заданного ключа.
Производительность. Это более эффективно проверять на нуль, чем проверять список, чтобы увидеть, пуст ли он... поэтому принятие этой идиомы в качестве стандарта может привести к более высокому идиоматическому коду производительности
Обратите внимание, что в Clojure все еще есть некоторые функции, которые возвращают пустой список. Примером является отдых:
(rest [1])
=> ()
Этот вопрос о покойном и следующем объясняет, почему это.....
Также обратите внимание, что объединение типов коллекций и nil образует моноид, с конкатенацией monoid plus и nil моноидным нулем. Таким образом, nil сохраняет пустую семантику списка под конкатенацией, а также представляет ложное или "отсутствующее" значение.
Python - это еще один язык, где общие моноидные идентификаторы представляют собой ложные значения: 0, пустой список, пустой кортеж.
Поскольку пустые коллекции действуют как
true
в булевых контекстах, вам нужна идиома для проверки того, есть ли что-нибудь в коллекции для обработки. К счастью, Clojure предоставляет такую технику:(seq [1 2 3]) ;=> (1 2 3) (seq []) ;=> nil
В других Lisps, таких как Common Lisp, пустой список используется как nil
. Это известно как nil punning и является только жизнеспособным, когда пустой список является ложным. Возврат nil
здесь Clojure способ повторного ввода nil punning.
Поскольку я написал комментарий, я напишу ответ. (Ответ skuro предоставляет всю информацию, но, возможно, слишком много)
seq
- это то, что каждый использует большую часть времени, но empty?
отлично подходит для его просто (not (seq lat))
when
имеет только одну ветвь, это очень полезно, если вы хотите иметь побочные эффекты. Вам не нужно использовать do
.См. этот пример:
(если false "() (do (println 1) (println 2) (println 3)))
вы можете написать
(когда true (println 1) (println 2) (println 3))
Не так, но я считаю, что лучше читать.
P.S.
Не то, что есть функции с именем if-not
и when-not
, они часто бывают лучше (if (not true) ...)