我自学Clojure。
在非FP语言中,我可以很容易地编写嵌套文件,如果我没有专门放置其他文件,那么控件就会流出if块。例如:
Thing myfunc()
{
if(cond1)
{
if(cond2)
return something;
}
return somethingelse;
}
然而,在Clojure中,没有返回声明(我知道),所以如果我写:
(defn myfunc []
(if (cond1)
(if (cond2) something))
somethingelse)
然后没有"返回"在"某事"。这似乎只是说,好吧,这里我们有一个价值,现在让我们继续执行。显而易见的解决方案是结合条件,即:
(if (and (cond1) (cond2))
something
somethingelse)
但是对于大型条件,这会变得笨拙/难看。此外,还需要额外的指导才能向" else"添加声明。 cond1的一部分。对此有什么优雅的解决方案吗?
答案 0 :(得分:33)
这是命令式和功能性方法之间的细微差别。通过命令,您可以将return
放在函数的任何位置,而功能最好的方法是拥有清晰明确的执行路径。有些人(包括我)在命令式编程中也更喜欢后一种方法,认为它更明显,更容易管理,更不容易出错。
使这个功能明确:
Thing myfunc() {
if(cond1) {
if(cond2)
return something;
}
return somethingelse;
}
您可以将其重构为:
Thing myfunc() {
if(cond1 && cond2) {
return something;
} else {
return somethingelse;
}
}
在Clojure中,它的等价物是:
(defn myfunc []
(if (and cond1 cond2)
something
somethingelse))
如果您需要“else”,您的Java版本可能会变为:
Thing myfunc() {
if(cond1) {
if(cond2) {
return something;
} else {
return newelse;
}
} else {
return somethingelse;
}
}
......及其Clojure等价物:
(defn myfunc []
(if cond1
(if cond2 something newelse)
somethingelse))
答案 1 :(得分:15)
(if (and (cond1) (cond2))
something
somethingelse)
(cond
(and (cond1) (cond2)) something
:else somethingelse)
如果你想比较同样的东西, cond
会这样做;在交换机案例中,您可以使用condp
。
我不经常看到那种代码,但这就是它的方法。
答案 2 :(得分:15)
命令式语言的if语句表示 if this then do that else do that
,而函数式语言的if表达式表示if this return that else return this
。这是一种不同的看待同一个想法的方式,它反映了表达问题的一种非常不同的方法。在函数式语言一切都有价值,真的是一切,即使你没有对这个值做任何事情。
当我进行过渡时,它帮助了很多人问自己“这个函数应该返回什么结果”,而不是我习惯要问的“这个函数应该做什么”的问题。
答案 3 :(得分:8)
在Clojure中没有明确的return语句,但是你的代码将“返回”“某事”,因为你在if
之后没有任何表达式,而在Clojure中,最后一个表达式的结果用作函数的返回值。
答案 4 :(得分:0)
您也可以使用(cond)
宏:
(defn length-checker [a b]
(cond
(= 3 (count (str a))) (if (= 3 (count (str b)))
(println "both numbers are 3 digits long")
(println "first number is 3 digits, but the 2nd not!"))
:else (println "first- or both of the numbers are not 3 digits")))
答案 5 :(得分:0)
core.match库提供了解决此问题的(imho)最易读的方法。
此代码段:
(defn myfunc []
(if (cond1)
(if (cond2) something))
somethingelse)
成为:
(ns my.project
(:require [clojure.core.match :refer [match]]))
(defn myfunc []
(match [cond1 cond2]
[true true] something
[_ _] somethingelse))
请注意,您可以匹配布尔值以外的其他值,例如匹配关键字(或与此相关的任何clojure值),例如:
(defn myfunc []
(match [cond1 some-kw another-kw]
[true :a :z] foo
[true :b _] gee
[true _ _] bar
[false _ _] giz
[_ _ _] default))
更多examples。