if-else ветвление в clojure - PullRequest
       1

if-else ветвление в clojure

27 голосов
/ 09 февраля 2011

Я учу себя Clojure.

На языке, не являющемся FP, я мог бы достаточно легко написать вложенный if, и, если бы я специально не вставил else, тогда управление просто вышло бы из блока 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. Есть ли какое-нибудь элегантное решение для этого?

Ответы [ 5 ]

33 голосов
/ 09 февраля 2011

Это тонкое различие между императивным и функциональным подходом.С императивом вы можете поместить return в любое место функции, в то время как с функционалом лучше всего иметь четкие и явные пути выполнения.Некоторые люди (включая меня) предпочитают последний подход и в императивном программировании, признавая его как более очевидный, управляемый и менее подверженный ошибкам.

Чтобы сделать эту функцию явной:Вы можете изменить его на:

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))
15 голосов
/ 09 февраля 2011

Imperative Languages ​​имеют операторы if, которые говорят if this then do that else do that, а функциональные языки имеют выражения if, которые говорят if this return that else return this. это другой взгляд на ту же идею, который отражает совершенно другой подход к выражению проблем. в функциональных языках все имеет значение , действительно все, даже если вы ничего не делаете с этим значением.

Когда я делал переход, мне очень помогло спросить себя, «какой результат должна вернуть эта функция» вместо вопроса «что должна делать эта функция», который я привык задавать.

15 голосов
/ 09 февраля 2011
(if (and (cond1) (cond2))
     something
     somethingelse)

(cond 
    (and (cond1) (cond2)) something
    :else somethingelse)

cond делает это, если вы хотите сравнить то же самое; в распределительном шкафу вы можете использовать condp.

Я не вижу такой код часто, но это способ сделать это.

8 голосов
/ 09 февраля 2011

В Clojure нет явного оператора return, но ваш код будет «возвращать» на «что-то», потому что после этого у вас нет выражений if, а в Clojure используется результат последнего выраженияв качестве возвращаемого значения функции .

0 голосов
/ 21 июля 2015

Вы также можете использовать макрос (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")))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...