我正在使用 clojure,虽然我之前曾涉足过 lisp,但我很难找到一种干净的方法来将 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)
, 但如果需要在 (first 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)))))
此代码遍历给定的list seq-able(列表、向量、数组...)向量并返回第一个元素为真的第一个向量的第二个元素(意思不是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 - 让里面条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2067832/