让我们假设我们应该对电子邮件地址和与电子邮件相关联的数据进行一系列检查:
检查电子邮件是否为零?如果没有返回{:msg“ emial is nil”}
检查电子邮件是否具有帐户(即对帐户进行数据库查找以获取电子邮件)。如果account为nil,则返回{:msg“ no account”}
检查帐户是否过期。如果accout未过期,则返回{:msg expired}
..依此类推
Currrently, I have coded this as nested if-let statements:
(if-let [email (if (nil? email) nil email)]
(if-let [acct (load-act email)]
(if-let [goodacct (if (expired? acct) nil acct)]
....
))
是否有更好的方法或更惯用的方式来编写此代码?
有几种方法可以考虑这一点:
1)将对电子邮件的零检查移到更高的位置。然后你的函数就可以了
(let [acct (load-act email)]
(cond (nil? acct) "no account"
(expired? acct) "account expired"
:else acct))
2)并非所有测试都确实需要保留结果。 if-let可以简化为
(if (nil? email)
"email is nil"
(if-let [acct (load-act email)]
(if (expired? acct)
"account expired"
acct)
"no account"))
[旁注-Clojure的虚假概念是nil
和false
。您正在使用nil?
检查,该检查仅真正检查nil
,并且也使用if-let
检查false
。有if-some
,仅进行nil
检查。
3)better-cond
允许在其cond构造内进行绑定:
better-cond
与@xificurC的最新版本相同。但是为什么不使用普通语法呢?不是更多的输入:
(b/cond
(nil? email) "email is nil"
:let [acct (load-act email)]
(nil? acct) "no account"
(expired? acct) "account expired"
:else acct)
当然,可以讨论第一个(cond (nil? email) {:msg "meail is nil"}
:else (let [acct (load-act email)]
(cond (nil? acct) {:msg "no account"}
(expired? acct) {:msg "expired account"}
:else acct)))
是否不应该是cond
。但是我喜欢if
,因为它在左右两边列出了非常好的因果关系。