2013-01-12 12 views
0

我是一名clojure的新手,并且对使用不同数据结构的contains?形式有点困惑。如何理解包含?应用于clojure的列表

contains应用于向量,集合或映射的结果就是我所期望的,它测试集合中是否存在键(或索引)。但是,当涉及到一个列表,如


(def li '(1 2 3)) ; define a list 
(contains? li 1) ; returns false !!?? 

我知道这不是那么简单了解如何contains?作品与列表,因为它的文件说,实施恒定或登录时运行。因此,如果1在列表或其索引范围内,那么在小于日志时间内进行测试是没有意义的。 但在这种情况下,为什么它只是引发一个异常,例如在应用assoc时出现一个列表。在assoc的情况下,哲学是相同的 - assoc不应该应用于列表,因为它不支持足够快速的随机访问其元素。

我觉得这很不方便,因为clojure中的很多表单返回一个普通的集合作为结果,如(vals a-map),所以为了测试一个元素是否存在于地图的值集中,不同的方法会给出不同的结果 - 但是我说他们只是说同样的事情的不同方式。


(def a-map {:one 1 :two 2}) 
(contains? (vals a-map) 1) ; returns false!! 
(contains? (set (vals a-map)) 1); returns true!! 

所以经过漫长的解释,我的问题是 - 这个设计背后的理性是什么?当我们想要测试一个元素是否在clojure中的一个地图的值集时,我们应该怎样说呢,更重要的是,我应该如何说服自己,以便在实践中不会犯愚蠢的错误?谢谢!

+0

已经有一个关于staksowerflow的问题的答案: http://stackoverflow.com/a/3249401/1202461。 –

+1

在提出任何问题之前,您应该搜索它。可能有人曾经问过它。 –

+2

感谢您的评论,但我仍然相信,线程只回答我的问题在这里的一部分。特别是,为什么它是这样设计的,而不是它的设计。而这是否意味着我们应该总是在使用contains时使用它?有一个列表? – dolaameng

回答

4

source code显示clojure直到并包括版本1.4 contains?总是返回false列表(它通过行713)。

latest 1.5 beta它会引发异常。

+0

整齐!感谢你的回答! – dolaameng

+0

1.5的变化是一个很好的变化。不少人最初都被这种行为所困惑。 –

1

contains?仅用于键控集合(例如,任意键/值对的映射,具有整数索引的索引集合的向量)。查看文档字符串:

clojure.core/contains? 
([coll key]) 
    Returns true if key is present in the given collection, otherwise 
    returns false. Note that for numerically indexed collections like 
    vectors and Java arrays, this tests if the numeric key is within the 
    range of indexes. 'contains?' operates constant or logarithmic time; 
    it will not perform a linear search for a value. See also 'some'. 

就个人而言,我认为这是严重命名,并应该被称为has-key?或类似的东西。但那已经是过去的历史了 - 除非有人(即Rich决定对API做出重大改变),否则我们会坚持下去。

尽管如此,如果contains?曾经导致您遇到问题,那么您可能会从算法的角度出错:您可能不应该按顺序搜索集合以查找值,您应该使用地图或者改为设置。

但是要回答这个问题:我同意你的观点,当应用于某些不支持键列查找(如列表)的情况下,包含异常会更有意义。它不与文档字符串矛盾,因为这种行为是不确定的,所以也许这是值得的补丁?

编辑:我从@ ivant的回答可以看出,最新的1.5测试版确实会在列表中引发异常。问题已经解决!