在Clojure中,如何将'and'应用于一个列表?

24
在闭包中,我们如何将and或其他宏应用于列表?
这样做是不起作用的:
(apply and '(true false))

因为apply无法获取宏的值。

那么,检查列表中所有元素是否为true的最佳方法是什么?


4个回答

37
你可以这样做代替:
(every? identity '(true false))

请查看此帖子以获取更多信息。


最近的版本中,这个用例有没有更好的解决方法? - matanster

7
在Clojure中,宏不像函数那样是一等公民,它们的组合方式不太一样,你不能将宏传递给其他函数或使用apply。这是因为在应用之前宏已经完成并结束了。
通常情况下,习惯将宏包装在函数中以便可以apply或将其传递给其他函数。
(defmacro my-macro [x y z] ...)

(apply #(my-macro %1 %2 %3) [1 2 3])

(map #(my-macro) [1 2 3] [:a :b :c] [a b c])

匿名函数读取宏#(使得这变得轻松,宏不是一等公民实际上并不会造成不便。只需尝试记住宏俱乐部的第一条规则即可。请参考

2
但是当宏接收到可变数量的参数时,这种方法将会崩溃。 - viebel
你正在违反宏编程俱乐部的第一条规则...是的,即使宏抽象也会泄漏 :( - Arthur Ulfeldt

5
你也可以这样做: (apply = true '(true false))

0
user=> (eval `(and ~@(list true false)))

false

user=> (eval `(and ~@ (list true true 1)))

1

我正在使用语法引用,然后使用大型铁锤删除集合周围的括号,并且由于我引用了它,必须使用 eval。如果您正在创建一个宏并且传递给其中的函数是“and”,则这很有用。

所以(list 1 2 3)经过铁锤处理变成了1 2 3

这是一种极其糟糕的方法,但它可以工作,所以我得到了那个不错的结果。虽然我的Clojure不是很好,但我希望这个宏示例能够澄清事情。

(defmacro split-my-args-then-apply-fn
  "This is one terrible macro designed to show the use of 'and'."
  [fun coll & args]
  `(~fun ~@((apply juxt args) coll)))

使用方法(不要):

(split-my-args-then-apply-fn 
    and 
    {:something :true :something-else false} 
    :something :something-else)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接