Clojure:申请或列表

时间:2013-09-06 23:03:02

标签: clojure

这个问题与In clojure, how to apply 'and' to a list?类似,但解决方案并不适用于我的问题。 every?函数只返回一个布尔值。

or是一个宏,因此此代码无效:

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

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

到目前为止我的想法:

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

2 个答案:

答案 0 :(得分:6)

您可能可以使用some

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

请注意,如果失败,则与or不同

(some identity [false]) ; = nil
(or false) ; = false

答案 1 :(得分:3)

一个简单的宏:

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

甚至更抽象

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

编辑:由于您抱怨在运行时无法运行,因此会提供一个在运行时工作的apply-macro版本。将其与此处发布的答案进行比较:In clojure, how to apply a macro to a list?

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

请注意,此版本使用的参数传递未评估(m未评估,如果这是一个函数,它会抛出,因为宏没有值)它使用concat来构建包含的列表带有引用的宏名称的列表,以及表单c(对于coll)的评估返回,以便将(range 5)作为range的完全评估列表eval回报。最后,它使用or来评估表达式。

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

对于运行时序列,使用every?和{{1}}显然更有意义。