Clojure if-then-else?

Это должен быть очень тривиальный вопрос. Я новичок в Clojure и записываю это if-then-else на основе: http://clojure.org/special_forms#Special%20Forms--%28if%20test%20then%20else?%29

Однако я продолжаю получать эту ошибку:

java.lang.Exception: Слишком много аргументов для if (NO_SOURCE_FILE: 424)

// This code has infinite recursion bugs; but it should compile!
(defn sumdown [sum x]
    (
    if (foo x) 
     (do
     (recur (+ sum x) (dec x))
     )
     else do(
        (recur (+ sum x) (dec x))
     )

     )
) 

Ответ 1

В шаблоне:

(if test then else?)

оба then и else не представляют ключевые слова, а фактические выражения. ? указывает, что выражение else не является обязательным.

Условие проверки оценивается и основывается на его значении, соответствующее выражение ветвления вычисляется и "возвращается" как значение всего выражения if.

Например, это определит функцию абсолютного значения:

(defn abs [x]
  (if (< x 0)
    (- x)
    x))

Ответ 2

(defn sumdown [sum x]
  (if (foo x)
    (recur (+ sum x) (dec x))
    (recur (+ sum x) (dec x))))

Это идиоматический способ написать этот код. Я рекомендую текстовый редактор /IDE с базовой поддержкой для редактирования источника Lisp (сопоставление парных/скобок/скобок).

Ответ 3

Правильная реализация вашего образца, удалив весь избыточный код, будет:

(defn sumdown
  [sum x]
  (recur (+ sum x) (dec x)))

Потому что и ваши предложения "then" и "else" идентичны, и "do являются избыточными (и в любом случае различные формы do do для побочных эффектов).

Другие условные обозначения для рассмотрения: когда, cond, condp и case.