【问题标题】:Non-map collection predicate?非地图集合谓词?
【发布时间】:2017-08-02 07:08:47
【问题描述】:

是否有表示“集合,但不是地图”的 Clojure 谓词?

这样的谓词是/将是有价值的,因为可以对除地图之外的所有集合执行许多操作。例如(apply + ...)(reduce + ...) 可以与向量、列表、惰性序列和集合一起使用,但不能与映射一起使用,因为在这样的上下文中映射的元素最终为clojure.lang.MapEntrys。我所知道的那些谓词导致问题的是集合和映射:

  • sequential? 对于向量、列表和惰性序列是正确的,但对于映射和集合都是错误的。 (seq? 类似,但对于向量来说是错误的。)
  • coll?seqable? 适用于布景和地图,以及我能想到的所有其他类型的收藏。

当然我可以定义这样的谓词,例如像这样:

(defn coll-but-not-map?
  [xs]
  (and (coll? xs) 
       (not (map? xs))))

或者像这样:

(defn sequential-or-set?
  [xs]
  (or (sequential? xs)
      (set? xs)))

我想知道是否有一个内置的 clojure.core(或贡献的库)谓词可以做同样的事情。

这个问题与this onethis one 有关,但他们的回答没有回答。 (如果我的问题与我没有找到的问题重复,我很高兴将其标记为这样。)

【问题讨论】:

  • 为什么你不知道你的函数得到什么数据结构? @Josh 用“否”回答了您的是/否问题,并提供了一些有用的建议。如果没有更多关于您正在尝试做的事情的背景信息,就很难为您提供帮助。尝试多种方法?
  • 感谢@Brandon 的提问。我正在递归到一个映射映射(映射(映射......)),其中叶节点要么是非映射数字集合,要么是其他诸如裸数字之类的东西。我想计算每个数字集合的统计数据,但不是裸数字。目前叶子集合都是序列,但为什么不把函数做得更通用,让它处理集合呢?另请参阅我对 fl00r 答案的评论。

标签: clojure


【解决方案1】:

例如 (apply + ...) 或 (reduce + ...) 可用于向量、列表、惰性序列和集合,但不能用于映射

我认为这与收藏无关。在您的情况下,您遇到的问题不是一般的 applyreduce 应用程序,而是特定的 + 功能。即使我们在这里使用矢量,(apply + [:a :b :c]) 也不起作用。

我的意思是,您正在尝试解决特定领域的问题,这就是 Clojure 本身没有通用解决方案的原因。因此,请使用您能想到的任何适当的谓词。

【讨论】:

  • 我理解你的意思,fl00r,但我认为除了地图之外的所有集合都有一些共同点:地图的元素始终有效MapEntrys。任何其他类型的收藏都不是这样。本质上,集合——除了地图——可以被视为任意选择类型的元素的集合(或序列,如果顺序无关紧要)。 + 只是一个插图(请参阅我对布兰登评论的回复)。我可以对其他类型的元素提出同样的观点。例如:没有任何映射的元素在传递给applyreduce 时是字符串。
  • @Mars 我明白了。但同样,从“序列”的角度来看,地图是向量列表(MapEntrys,但仍然如此)。所以你的地图{:a 1 :b 2}本质上是一个列表([:a 1], [:b 2]),对吧?我同意地图在这种方式上有所不同,但对于这种情况,map? 谓词似乎非常自然且非常明确。
  • 我同意。 map? 在很多情况下就足够了。但是,(not (map? x)) 对非集合是正确的,因此识别非映射集合需要合取或析取。我现在正在考虑是否可以为语言添加具有此含义的接口。我认为这是个好主意,但很难卖给 RH 等人。
【解决方案2】:

我发现或使用的没有任何符合此描述的内容。我认为你自己的谓词函数清晰、简单,如果你觉得有用的话,很容易将其包含在你的代码中。

也许您正在编写的代码必须非常通用,但通常情况下,函数既接受又返回一致类型的数据。在某些情况下这是不正确的,但通常情况下,如果一个函数可以成为万事通,那么它做的太多了。

使用您的示例 - 添加数字向量、数字列表或一组数字是有意义的。但是数字地图?这是没有意义的,除非它可能是映射中包含的值,在这种情况下,期望单个代码处理添加顺序数据和关联数据是不合理的。该函数应该得到它期望的东西,并且它应该返回一致的东西。这让我想起了 Stuart Sierra 的 blog post 讨论这方面的一致性。没有更多信息,我只是猜测您的用例,但需要考虑。

【讨论】:

  • 谢谢乔希。请看我的 cmets 对 Brandon 和 fl00r 的回应。
  • 任意选择两个答案之一作为接受。经过这么长时间,应该有人得到积分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 2016-11-08
  • 2019-03-17
  • 2010-10-07
  • 2023-03-13
相关资源
最近更新 更多