从Clojuredoc的示例和注释中获取函数every?
user> (every? true? '()) ;empty is true?
true
user> (every? false? '()) ;empty is false?
true
这确实很奇怪,也可能是不合逻辑的,正如我对上述两者所期望的那样。有人可以说明这背后的理由吗?
答案 0 :(得分:38)
在数学中,特别是在谓词逻辑领域,关于空集的每个通用谓词都是正确的。例如,以下陈述为真:
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)),它等同于形式{{的含义1}}( X的X元素意味着P(x))。由于这个含义的左侧对于空集合是假的(即,没有元素x使得x∈X ⇒ P(x)
,这只是空集的定义),暗示是真的(即,{ {1}}评估为true;检查truth table here)。
这正是您在所显示的代码中看到的内容:Clojure正在将空列表x∈Ø
上的通用谓词false ⇒ whatever
评估为true,根据谓词,这是正确且完全合乎逻辑的逻辑。
最后,您可以期望在每个功能语言或功能库上看到完全相同的行为,使用同义词(every? pred)
,'()
和其他人。如果你探索这些函数的实现,你会发现一个共同的模式:函数将返回true,除非它找到一个反例,即谓词为false的元素;如果它没有找到这样的元素(包括根本没有找到任何元素 - 空集)那么它就不能证明谓词是假的,并返回true。这可以通过循环或折叠来完成,具体取决于语言或框架,但这个想法总是相同的。
例如,检查:
Iterables.all
(and, more specifically, Iterators.all
) 强>;或List.forall
强>;或forall
强>;或all
强>;或Array.every
强>;或every
强>;或Seq.forall
强>;或Enumerable.All
强>;或all_of
强>;或all
强>;或all?
强> (它们与Clojure中的all
完全相同;可以随意编辑和添加您喜欢的语言或库!)。
有关更多信息,请务必阅读维基百科关于 Universal Quantification 和 Vacuous truth 的文章。
答案 1 :(得分:6)
我们有3种可能的情况,一次只有一种情况适用于集合。
现在,如果你考虑为空列表返回false,它也会感觉很奇怪,因为当coll中的至少一个项目使谓词失败但是没有发生的空列表时会返回false。
我认为选择真空的合理理由是基于这样一个事实,即在现实世界中这种情况适用的情况与没有意义的情况相比更多。例如:有人给了我一个URL列表,我需要返回他们下载的内容,现在我的函数首先要验证每个URL是否格式正确,然后使用map或pmap下载URL -
(if (every? url? urls) (map download urls) (throw "Invalid url found"))
这种以及更多此类示例将使序列的处理更加无缝。
另一方面,我是一个静态类型的语言家伙(如Haskell),并且更喜欢使用类型来解决这个问题。我不希望返回true或false,而是希望此函数返回Maybe bool
,以便:
Just True
Just False
Nothing