Подтвердить что ты не робот

Почему Clojure idiom предпочитает возвращать нуль вместо пустого списка, такого как Scheme?

Из комментария к другому вопросу, кто-то говорит, что Clojure idiom предпочитает возвращать нуль, а не пустой список, как на Схеме. Почему это?

Как

(when (seq lat) ...)

вместо

  (if (empty? lat)  
    '() ...)
4b9b3361

Ответ 1

Я могу думать о нескольких причинах:

  • Логическое различие. В 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])
=> ()

Этот вопрос о покойном и следующем объясняет, почему это.....

Ответ 2

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

Python - это еще один язык, где общие моноидные идентификаторы представляют собой ложные значения: 0, пустой список, пустой кортеж.

Ответ 3

Из Радость Clojure

Поскольку пустые коллекции действуют как true в булевых контекстах, вам нужна идиома для проверки того, есть ли что-нибудь в коллекции для обработки. К счастью, Clojure предоставляет такую ​​технику:

(seq [1 2 3])
;=> (1 2 3)

(seq [])
;=> nil

В других Lisps, таких как Common Lisp, пустой список используется как nil. Это известно как nil punning и является только жизнеспособным, когда пустой список является ложным. Возврат nil здесь Clojure способ повторного ввода nil punning.

Ответ 4

Поскольку я написал комментарий, я напишу ответ. (Ответ skuro предоставляет всю информацию, но, возможно, слишком много)

  • Прежде всего, я думаю, что более важные вещи должны быть в первую очередь.
  • seq - это то, что каждый использует большую часть времени, но empty? отлично подходит для его просто (not (seq lat))
  • В Clojure '() истинно, поэтому вы хотите вернуть что-то false, если последовательность завершена.
  • если в вашем случае есть только одна ветвь importend, если другая возвращает false/'() или что-то подобное, почему вы должны записать эту ветку. 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) ...)