Подтвердить что ты не робот

If-else, ветвящийся в clojure

Я учу себя Clojure.

В языке, отличном от FP, я мог бы легко написать вложенные if, и если бы я не специально помещал else, тогда управление просто выходило бы из блока if. Например:

Thing myfunc()
{
  if(cond1)
  {
    if(cond2)
      return something;
  }
  return somethingelse;
}

Однако в Clojure нет оператора return (который я знаю), поэтому, если я пишу:

(defn myfunc []
  (if (cond1)
      (if (cond2) something))
  somethingelse)

тогда нет "возврата" на "что-то". Кажется, это просто сказать, хорошо, здесь у нас есть ценность, теперь пусть продолжит выполнение. Очевидным решением было бы объединение условий, т.е.:

(if (and (cond1) (cond2))
    something
    somethingelse)

но это становится громоздким/уродливым при больших условиях. Кроме того, для добавления заявления в "else" часть cond1 потребуется дополнительное обновление. Есть ли какое-то элегантное решение для этого?

4b9b3361

Ответ 1

Это тонкая разница между императивным и функциональным подходом. С императивностью вы можете разместить 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))

Ответ 2

(if (and (cond1) (cond2))
     something
     somethingelse)

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

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

Вы также можете использовать макрос (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")))