Почему идиома Clojure предпочитает возвращать ноль вместо пустого списка, как Схема? - PullRequest
14 голосов
/ 18 мая 2011

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

Как,

(when (seq lat) ...)

вместо

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

Ответы [ 4 ]

23 голосов
/ 18 мая 2011

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

  • Логическое различие .В Clojure ноль означает ничего / отсутствие значения.Принимая во внимание, что '() "пустой список является значением - это просто значение, являющееся пустым списком. Очень часто концептуально и логически полезно различать два.

  • Подходит с JVM - объектная модель JVM поддерживает нулевые ссылки. И многие API Java возвращают ноль, чтобы означать «ничего» или «значение не найдено». Так что для обеспечения легкой JVMсовместимость, для Clojure имеет смысл использовать nil аналогичным образом.

  • Laziness - логика здесь довольно сложная, но я понимаю, что использование nil для«no list» лучше работает с ленивыми последовательностями Clojure . Поскольку Clojure по умолчанию является ленивым функциональным языком программирования, имеет смысл для этого использования быть стандартным. См. http://clojure.org/lazy для дополнительного пояснения.

  • «Ложь» - Удобно использовать ноль для обозначения «ничего», а также для «ложного» при написании условного кода, который проверяет коллекции - так что вы можетекод записи, например (if (some-map :some-key) ....), чтобы проверить, содержит ли хэш-карта значение для данного ключа.

  • Производительность - более эффективно проверять ноль, чем проверятьсписок, чтобы увидеть, пуст ли он ... следовательно, принятие этой идиомы в качестве стандарта может привести к повышению производительности идиоматического кода

Обратите внимание, что в Clojure все еще есть некоторые функции, которые возвращают пустой список,Примером является rest:

(rest [1])
=> ()

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

7 голосов
/ 20 августа 2012

Также обратите внимание, что объединение типов коллекции и nil образуют моноид, с конкатенацией моноид плюс и ноль моноид ноль.Таким образом, nil сохраняет семантику пустого списка при конкатенации, одновременно представляя ложное или «отсутствующее» значение.

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

5 голосов
/ 10 марта 2015

С Радость Clojure

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

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

(seq [])
;=> nil

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

1 голос
/ 18 мая 2011

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

  1. Прежде всего, я думаю, что в первую очередь должны быть более важные вещи.
  2. seq - это то, что всеиспользует большую часть времени, но empty? подходит для его просто (not (seq lat))
  3. В Clojure '() имеет значение true, поэтому обычно вы хотите вернуть что-то false, если последовательность завершена.
  4. если у вас есть только одна важная ветвь в вашей, если другая возвращает false / '() или что-то в этом роде, почему вы должны записать эту ветку?when имеет только одну ветвь, это особенно хорошо, если вы хотите иметь побочные эффекты.Вам не нужно использовать do.

См. Этот пример:

(если false '() (do (println 1) (println 2) (println 3).


PS

Не то чтобы существуют функции, называемые if-not и when-not, они часто лучше, чем (if (not true) ...)

...