这个问题与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
答案 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}}显然更有意义。