if-else在clojure中分支

时间:2011-02-09 10:32:40

标签: functional-programming clojure

我自学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的一部分。对此有什么优雅的解决方案吗?

6 个答案:

答案 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