Clojure 合并函数
SQL 提供了一个名为 coalesce(a, b, c, ...)
的函数,如果所有参数都为 null,则该函数返回 null,否则返回第一个非 null 参数。
你会如何用 Clojure 编写这样的东西?
它将像这样调用:(coalesce f1 f2 f3 ...)
,其中 fi
是仅在需要时才进行评估的形式。如果f1
非零,则不应评估f2
——它可能会产生副作用。
也许 Clojure 已经提供了这样的函数(或宏)。
编辑:这是我提出的一个解决方案(修改自 Stuart Halloway 的《Clojure 编程》,第 206 页的 (and ...)
宏):
(defmacro coalesce
([] nil)
([x] x)
([x & rest] `(let [c# ~x] (if c# c# (coalesce ~@rest)))))
似乎有效。
(defmacro coalesce
([] nil)
([x] x)
([x & rest] `(let [c# ~x] (if (not (nil? c#)) c# (coalesce ~@rest)))))
固定的。
SQL offers a function called coalesce(a, b, c, ...)
that returns null if all of its arguments are null, otherwise it returns the first non-null argument.
How would you go about writing something like this in Clojure?
It will be called like this: (coalesce f1 f2 f3 ...)
where the fi
are forms that should only be evaluated if required. If f1
is non-nil, then f2
should not be evaluated -- it may have side-effects.
Maybe Clojure already offers such a function (or macro).
EDIT: Here a solution that I came up with (modified from Stuart Halloway's Programming Clojure, (and ...)
macro on page 206):
(defmacro coalesce
([] nil)
([x] x)
([x & rest] `(let [c# ~x] (if c# c# (coalesce ~@rest)))))
Seems to work.
(defmacro coalesce
([] nil)
([x] x)
([x & rest] `(let [c# ~x] (if (not (nil? c#)) c# (coalesce ~@rest)))))
Fixed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你想要的是“或”宏。
http://clojuredocs.org/clojure_core/clojure.core/or
如果您只想要 nil 而不是 false ,请执行以下操作重写 和 并将其命名为合并。
编辑:
这不能作为函数来完成,因为函数首先评估它们的所有参数。这可以在 Haskell 中完成,因为函数是惰性的(对于 Haskell 的事情不是 100% 确定)。
What you want is the "or" macro.
http://clojuredocs.org/clojure_core/clojure.core/or
If you only want nil and not false do a rewrite of and and name it coalesce.
Edit:
This could not be done as a function because functions evaluate all their arguments first. This could be done in Haskell because functions are lazy (not 100% sure about the Haskell thing).
基于 nickik 的回答和“或”clojure 宏:
Based on nickik's answer and "or" clojure macro:
您可以使用 1.2 中介绍的内容:
编辑:扩展答案一点点。用于直接调用的宏。例如的助手。 apply+lazy seq 生成值。
然而,为了防止对价值观进行评估,我们需要一些本土的方式。
丑陋:
代码复杂一些,但更漂亮:
You could use keep introduced in 1.2:
EDIT: extended answer a little bit. Macro for direct invokations. Helper for eg. apply + lazy seq producing the values.
However to prevent evaluation of the values one needs some home-grown way.
Ugly:
A little more involved but prettier in the code:
如果您不想使用宏,则合并的某些函数版本:
用法:
与规范不同,这将评估所有参数。如果您想要短路评估,请使用
或
或其他适当的宏解决方案。Some function versions of coalesce, if you'd rather avoid macros:
Usage:
Unlike the spec, this will evaluate all args. Use
or
or another appropriate macro solution if you want short circuiting evaluation.也许我误解了这个问题,但这不只是第一个过滤元素吗?
例如:
它可以缩短为:
Perhaps I'm misapprehending the question, but isn't this just the first filtered element?
E.g.:
It could be shortened up to: