【问题标题】:How to understand contains? applied to a list in clojure [closed]如何理解包含?应用于clojure中的列表[关闭]
【发布时间】:2012-12-26 20:54:20
【问题描述】:

我是 clojure 的新手,对将 contains? 表单用于不同的数据结构有点困惑。

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


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

我知道要理解contains? 如何与列表一起工作并不是那么简单,因为它的文档说实现在常量或日志时间内运行。因此,如果 1 在列表或其索引范围内,那么在少于日志时间的时间内进行测试是没有意义的。 但在那种情况下,为什么它不只是引发一个异常,比如将assoc 与列表一起应用。在assoc 的情况下,原理是相同的——assoc 不应该应用于列表,因为它不支持对其元素进行足够快的随机访问。

我觉得很不方便,因为clojure中的很多表单都返回一个通用集合作为结果,比如(vals a-map),所以要测试一个元素是否存在于一个map的值集中,不同的方法给出不同的结果——但是对我来说,它们只是说同一件事的不同方式。


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

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

【问题讨论】:

  • 在 staksowerflow 上已经有你的问题的答案:stackoverflow.com/a/3249401/1202461
  • 在问任何问题之前,您应该搜索它。可能之前有人已经问过了。
  • 感谢您的评论,但我仍然相信该线程仅回答了我的部分问题。特别是为什么它是这样设计的,而不是它是如何设计的。这是否意味着我们应该在使用包含时始终解决它?有清单吗?
  • contains? 告诉您来自get 的结果是否真的在集合中。如果后者不适用,那么前者也不适用。

标签: data-structures clojure functional-programming contains


【解决方案1】:

source code 表明,对于 clojure 直到并包括 1.4 版,contains? 对于列表总是返回 false(它一直到第 713 行)。

latest 1.5 beta会抛出异常。

【讨论】:

  • 整洁!感谢您的回答!
  • 1.5 的变化是好的。不少人最初对这种行为感到困惑。
【解决方案2】:

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 测试版确实会在列表中引发异常。问题已经解决了!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    相关资源
    最近更新 更多