Clojure 为什么不';t默认情况下,when-let和if-let支持多个绑定?
为什么让默认情况下不支持多个绑定,而让默认情况下不支持多个绑定 因此: …而不是:Clojure 为什么不';t默认情况下,when-let和if-let支持多个绑定?,clojure,Clojure,为什么让默认情况下不支持多个绑定,而让默认情况下不支持多个绑定 因此: …而不是: (when-let [a ... (when-let [b ... (+ a b))) 我知道我可以编写自己的宏或使用monad(如下所述:)。因为(至少对于if let),不清楚如何处理“else”案例 至少,在我的激励下,我开始写一个宏来实现这一点。给定 (if-let* [a ... b ...] action other) 它将产生 (if-let [a ...
(when-let [a ...
(when-let [b ...
(+ a b)))
我知道我可以编写自己的宏或使用monad(如下所述:)。因为(至少对于if let
),不清楚如何处理“else”案例
至少,在我的激励下,我开始写一个宏来实现这一点。给定
(if-let* [a ...
b ...]
action
other)
它将产生
(if-let [a ...]
(if-let [b ...]
action
?))
我不清楚如何继续(还有两个地方是“其他”)
您可以说,对于任何失败都应该有一个单一的替代方案,或者在let时,对于应该没有替代方案,但是如果任何测试状态发生变化,那么事情仍然会变得一团糟
简言之,它比我预期的要复杂一点,因此我想当前的方法避免了需要对解决方案进行调用
另一种说法是:假设if let
应该像let
那样嵌套。更好的模型可能是cond
,它不是一个“嵌套if”,而是一个“替代if”,因此不适合范围。。。或者,还有另一种说法:如果
不能更好地处理这种情况。如果您使用,那么您可能会发现有一个mlet
函数非常有用:
如您所见,mlet遇到nil值时会短路
(第6.5.1节无)以下是let*:
(defmacro when-let*
"Multiple binding version of when-let"
[bindings & body]
(if (seq bindings)
`(when-let [~(first bindings) ~(second bindings)]
(when-let* ~(vec (drop 2 bindings)) ~@body))
`(do ~@body)))
user=> (when-let* [a 1 b 2 c 3]
(println "yeah!")
a)
;;=>yeah!
;;=>1
user=> (when-let* [a 1 b nil c 3]
(println "damn! b is nil")
a)
;;=>nil
(defmacro if-let*
"Multiple binding version of if-let"
([bindings then]
`(if-let* ~bindings ~then nil))
([bindings then else]
(if (seq bindings)
`(if-let [~(first bindings) ~(second bindings)]
(if-let* ~(vec (drop 2 bindings)) ~then ~else)
~else)
then)))
用法:
(defmacro when-let*
"Multiple binding version of when-let"
[bindings & body]
(if (seq bindings)
`(when-let [~(first bindings) ~(second bindings)]
(when-let* ~(vec (drop 2 bindings)) ~@body))
`(do ~@body)))
user=> (when-let* [a 1 b 2 c 3]
(println "yeah!")
a)
;;=>yeah!
;;=>1
user=> (when-let* [a 1 b nil c 3]
(println "damn! b is nil")
a)
;;=>nil
(defmacro if-let*
"Multiple binding version of if-let"
([bindings then]
`(if-let* ~bindings ~then nil))
([bindings then else]
(if (seq bindings)
`(if-let [~(first bindings) ~(second bindings)]
(if-let* ~(vec (drop 2 bindings)) ~then ~else)
~else)
then)))
这里是if let*:
(defmacro when-let*
"Multiple binding version of when-let"
[bindings & body]
(if (seq bindings)
`(when-let [~(first bindings) ~(second bindings)]
(when-let* ~(vec (drop 2 bindings)) ~@body))
`(do ~@body)))
user=> (when-let* [a 1 b 2 c 3]
(println "yeah!")
a)
;;=>yeah!
;;=>1
user=> (when-let* [a 1 b nil c 3]
(println "damn! b is nil")
a)
;;=>nil
(defmacro if-let*
"Multiple binding version of if-let"
([bindings then]
`(if-let* ~bindings ~then nil))
([bindings then else]
(if (seq bindings)
`(if-let [~(first bindings) ~(second bindings)]
(if-let* ~(vec (drop 2 bindings)) ~then ~else)
~else)
then)))
用法:
user=> (if-let* [a 1
b 2
c (+ a b)]
c
:some-val)
;;=> 3
user=> (if-let* [a 1 b "Damn!" c nil]
a
:some-val)
;;=> :some-val
编辑:事实证明绑定不应该以else形式泄漏。如果让*
宏泄漏,也可以很好地回答我的问题;)但是它并不存在——我看不到处理“else”部分的好方法。你不能只使用other
两次吗(如果让[a…](如果让[b…]操作其他)其他))
?@andrewcooke“你可以说应该有一个单一的替代方案”:没错。当所有窗体的计算结果均为true时执行操作
,当至少有一个窗体为NIL时执行其他
(另请参见)。但我不明白你为什么担心易变性。我根据你的要求编写了一个函数。希望它能有所帮助!这里可以找到一个更健壮的版本