3

这个问题类似于说,在clojure中,如何将“和”应用于列表?,但解决方案不适用于我的问题。every?函数只返回一个布尔值。

or是一个宏,所以这段代码是无效的:

(apply or [nil 10 20])  ; I want to get 10 here, as if 'or was a function.

使用not-every?我只会得到布尔值,但我想保留语义or- “真”元素应该是表达式的值。这样做的惯用方法是什么?

到目前为止我的想法:

(first (drop-while not [nil 10 20]))  ; = 10
4

2 回答 2

6

您也许可以为此使用some

(some identity [nil 10 20]) ; = 10

请注意,这与or失败时不同

(some identity [false]) ; = nil
(or false) ; = false
于 2013-09-06T23:23:25.917 回答
3

一个简单的宏:

(defmacro apply-or
  [coll]
  `(or ~@coll))

或者更抽象

(defmacro apply-macro
  [macro coll]
  `(~macro ~@coll))

编辑:由于您抱怨不能在运行时工作,所以这里有一个可以在运行时工作的 apply-macro 版本。将其与此处发布的答案进行比较:在 clojure 中,如何将宏应用于列表?

(defmacro apply-macro-in-runtime
  [m c]
  `(eval (concat '(~m) ~c)))

请注意,此版本利用未评估传递的参数(未评估 m,如果这是一个函数,它将抛出,因为宏没有值)它用于concat构建一个列表,该列表包含带有引用的宏的列表-名称和任何形式 c 的评估(对于 coll)返回,以便 c as(range 5)将被完全评估为返回的列表range。最后,它用于eval评估表达式。

澄清:这显然使用了 eval ,这会导致开销。但请注意,上面链接的答案中也使用了 eval 。由于 的递归定义,这也不适用于大序列or。很高兴知道这是可能的。

同样对于运行时序列,使用someand显然更有意义every?

于 2013-09-07T13:07:35.213 回答