检查集合是否为空的正确"clojure方式"是什么

sen*_*ngs 23 clojure

我想编写一个函数,如果给定的集合不为空,则返回布尔值true,否则返回false.

我也可以

defn ..
(boolean (seq coll))
Run Code Online (Sandbox Code Playgroud)

要么

defn ..
(not (empty? coll))
Run Code Online (Sandbox Code Playgroud)

由于我是clojure的新手,我最初倾向于使用#2(更具可读性),但是clojure api参考empty?明确表示使用成语(seq coll)代替(not (empty? coll)),可能是为了避免双重否定.

我想知道什么是clojure方法来检查集合是否为非空并返回布尔值true/false.

mat*_*ard 26

根据Clojure的喜悦,nil punning with seq是惯用的:

(defn print-seq [s]
  (when (seq s)
    (prn (first s))
    (recur (rest s))))
Run Code Online (Sandbox Code Playgroud)

"... seq作为终止条件的使用是测试序列是否为空的惯用方法.如果我们测试[在上面的例子中] s而不是(seq s),那么即使对于空集合也不会发生终止条件. ".


Mic*_*zyk 12

empty?您提到的文档字符串的段落特别意味着这样的nonempty?函数永远不应该是必需的,甚至特别有用,因为seq在布尔上下文中它总是可以代替它,在纯Clojure代码中它可以.

如果您觉得有必要编写这样的功能,我会说我更喜欢第一种方法.无论如何empty?都是建立起来seq的,所以没有避免的称呼它; 只是将结果转换为布尔似乎比两次旅行更清晰not.对于其他选项,请参阅例如nil?,false?(我仍然喜欢演员表).

顺便说一下,你为什么要写这个...?用于调用带有boolean参数的Java方法?在这种情况下,我认为演员会很好地表达意图.

更新:举例说明后一点:

  1. 一个简单的Java类:

    public class Foo {
      public static boolean foo(boolean arg) {
        return !arg;
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 一些Clojure客户端代码:

    (Foo/foo nil)
    ; => NullPointerException
    (Foo/foo (boolean nil))
    ; => true
    
    Run Code Online (Sandbox Code Playgroud)

  • 事实上,我们可以`(defalias truthy?boolean)`. (6认同)

Rob*_*lan 5

除了 Michal Marczyk 的出色回答之外,我还要指出还有一个特定的非空函数:

http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/not-empty

但它并不完全符合您的要求。(尽管它在大多数情况下都有效)。

如果集合为空,Not-empty 返回 nil;如果集合不为空,则返回集合本身。对于谓词测试,这将运行良好。如果您确实需要 true 和 false 值,那么 (not (empty? x)) 就是您所追求的。

  • 使用非空作为谓词是愚蠢的。在谓词上下文中,not-empty 只是 seq 的冗长且缓慢的版本。not-empty 的真正用途是当你想在测试空性时“let”一个本地变量,而不通过顺序视图破坏类型信息:“(if-let [coll (not-empty coll)] ... )`。例如,如果 coll 是一个映射,这可以让您测试是否为空,而无需转换为 seq。 (6认同)
  • @amalloy `not-empty` 比 `seq` 更具可读性,级别更低,并且具有完全相同的速度,正如您在 https://github.com/clojure/clojure/blob/ 查看其源代码所看到的那样clojure-1.7.0/src/clj/clojure/core.clj#L5302 (6认同)