В clojure (каждый? Pred coll) возвращает true, если coll пуст, может ли это быть дефектом дизайна? - программирование
Подтвердить что ты не робот

В clojure (каждый? Pred coll) возвращает true, если coll пуст, может ли это быть дефектом дизайна?

Из примера и комментария к Clojuredoc для функции каждый?

user> (every? true? '())    ;empty is true? 
true

user> (every? false? '())    ;empty is false? 
true

Это действительно странно и, возможно, нелогично, поскольку я ожидал бы ложного для обоих выше. Может ли кто-нибудь пролить свет на обоснование этого?

4b9b3361

Ответ 1

В математике, особенно в области логики предикатов, принято, что каждый универсальный предикат о пустом множестве истинен. Например, верно следующее утверждение:

Every integer in the empty set is even.

Аналогично, верно и следующее утверждение:

Every integer in the empty set is odd.

Следовательно, справедливо и следующее причудливое утверждение:

Every integer in the empty set is simultaneously even and odd.

Подумайте об этом: можете ли вы дать встречный пример любому из вышеперечисленных?

Более формальное объяснение будет следующим. Когда у вас есть универсальный предикат, который может быть формально записан как ∀x∈XP(x) (для всего x элемента X, P (x)), он эквивалентен импликации формы x∈X ⇒ P(x) (элемент x из X влечет за собой P ( Икс)). Поскольку левая часть этой импликации ложна для пустого множества (т.е. Нет элементов x таких, что x∈Ø, что является просто определением пустого множества), импликация истинна (т.е. false ⇒ whatever оценивается как true, проверьте таблицу истинности здесь).

Это именно то, что вы видите в коде, который вы показали: Clojure оценивает универсальный предикат (every? pred) в пустом списке '() как истинный, который является правильным и совершенно логичным в соответствии с логикой предикатов.

Наконец, вы можете ожидать увидеть то же самое поведение на каждом функциональном языке или функциональной библиотеке с синонимами all, forall и, возможно, другими. Если вы исследуете реализацию этих функций, вы заметите общий шаблон: функция вернет true, если не найдет встречный пример, т.е. Элемент, для которого предикат является ложным; если он не находит такой элемент (который включает в себя не обнаружение какого-либо элемента вообще - пустое множество), то он не может доказать, что предикат является ложным, и возвращает true. Это делается либо с помощью циклов или складок, в зависимости от языка или структуры, но идея всегда одна и та же.

Например, проверьте:

(все они делают то же самое, что и (every? pred coll) в Clojure, и не стесняйтесь редактировать и добавлять свой любимый язык или библиотеку!).

Для получения дополнительной информации не забудьте прочитать статьи в Википедии Универсальная количественная оценка и Свободная правда.

Ответ 2

У нас есть 3 возможных ситуации, только одна за раз применима к коллекции.

  • В коллекциях есть элементы, и все они являются предикатами - True
  • Один из элементов в coll завершил предикат - False
  • Колла пуста -??

Теперь, если вы думаете о возврате false для пустого списка, это также было бы странным, потому что false возвращается, когда хотя бы один элемент в coll завершил предикат, но для пустого списка это не произошло.

Я думаю, что рациональное выражение true для пустого колла было основано на том факте, что число случаев, когда это применимо в реальном мире, было больше по сравнению с тем, где это не имело бы смысла. Например: кто-то дал мне список URL-адресов, и мне нужно вернуть их загруженный контент, теперь моя функция сначала хочет проверить, что каждый URL-адрес в правильном формате, а затем использовать карту или pmap для загрузки URL-адресов -

(if (every? url? urls) (map download urls) (throw "Invalid url found"))

Этот и другие примеры такого рода сделают работу с последовательностями более плавной.

С другой стороны, я являюсь статически типизированным языком (например, Haskell) и предпочитаю использовать типы для решения этой проблемы. Вместо того, чтобы возвращать true или false, я хотел бы, чтобы эта функция возвращала Maybe bool такую, что:

  • Каждый элемент в столбце передает предикат - Just True
  • Один из элементов в coll не смог выполнить предикат - Just False
  • Колла пуста - Nothing