我正在使用clojure,并且虽然以前接触过lisps,但是在寻找一种干净的方法来将let语句嵌套在cond语句中时遇到了麻烦。例如,考虑以下功能:
(defn operate-on-list [xs]
(let [[unpack vector] (first xs)]
(cond
[(empty? xs) 'empty
unpack vector
:else (operate-on-list (rest xs))])))
这是对列表的相当标准的递归操作,但是在使用内容之前,它需要对列表中的第一个元素做一些工作。当然,问题在于列表可能为空。
在此示例中,将
unpack
更改为((first xs) 0)
并将vector
更改为((first xs) 1)
并不困难,但是如果需要在第一个xs上进行更多工作,这很快就会变得很丑陋。有什么方法可以在cond途中有效地使用let语句吗?
谢谢。
-内特
最佳答案
在这种情况下,最好使用if-let
:
(defn operate-on-list [xs]
(if-let [[unpack v] (first xs)]
(cond
unpack v
:else (operate-on-list (rest xs)))))
此代码遍历给定的向量列表可序列化(列表,向量,数组...),并返回第一个向量的第二个元素,其第一个元素为true(表示
false
或nil
不是)。如果找不到这样的向量,则返回nil
。请注意,
vector
是内置函数,因此,我选择了v
作为变量名,以防万一将来需要在体内使用该函数。更重要的是,您在cond语法中使用了太多括号;在此版本中已修复。更新:关于
if-let
的另外两点值得注意:if-let
的工作方式,如果(first xs)
恰好是nil
(false
相同),则不会发生破坏性绑定(bind),因此Clojure不会提示无法将nil
绑定(bind)到[unpack v]
。 if-let
接受else子句(在其中您不能引用if-let
绑定(bind)向量中绑定(bind)的变量-尽管如果您在else子句中,您仍然知道它们在false
或nil
的位置)。 关于lisp - 让内cond,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2067832/