Clojure合并功能

Ral*_*lph 13 clojure coalesce

SQL提供了一个函数coalesce(a, b, c, ...),如果它的所有参数都为null,则返回null,否则返回第一个非null参数.

你会如何在Clojure中写这样的东西?

它将被调用如下:(coalesce f1 f2 f3 ...)其中的fi表单只应在需要时进行评估.如果f1是非零,则f2不应评估 - 它可能有副作用.

也许Clojure已经提供了这样的功能(或宏).

编辑:这是我提出的一个解决方案(修改自Stuart Halloway的Programming Clojure,(and ...)第206页的宏):

(defmacro coalesce
  ([] nil)
  ([x] x)
  ([x & rest] `(let [c# ~x] (if c# c# (coalesce ~@rest)))))
Run Code Online (Sandbox Code Playgroud)

似乎工作.

(defmacro coalesce
  ([] nil)
  ([x] x)
  ([x & rest] `(let [c# ~x] (if (not (nil? c#)) c# (coalesce ~@rest)))))
Run Code Online (Sandbox Code Playgroud)

固定.

nic*_*kik 24

你想要的是"或"宏.

从左到右逐个评估exprs.如果表单返回逻辑true值,或返回该值并且不评估任何其他表达式,否则返回最后一个表达式的值.(或)返回nil.

http://clojuredocs.org/clojure_core/clojure.core/or

如果您只想要nil而不是false,请重写并命名为coalesce.

编辑:

这不能作为函数完成,因为函数首先评估所有参数.这可以在Haskell中完成,因为函数是懒惰的(不是100%肯定Haskell的事情).


Arj*_*jan 4

基于 nickik 的回答和“或”clojure 宏:

(defmacro coalesce
    ([] nil)
    ([x] x)
    ([x & next]
       `(let [v# ~x]
           (if (not (nil? v#)) v# (coalesce ~@next)))))
Run Code Online (Sandbox Code Playgroud)

  • 为什么要对“or”宏进行 1:1 重写? (3认同)
  • @Ralph:所以你想要第一个不是零或者第一个不是假值? (2认同)