Как перевести этот фрагмент императивного кода в код Clojure

Обычно у нас есть такая ситуация в C++

int a=0;
if(some_condition_satisfied(g)) {
   a = eval(g);  // never returns 0
}
if(a!=0) {
  do_something();
}

Как я могу сделать это в Clojure без использования ссылок, потому что я не могу назначить после инициализации?

Спасибо.


person user855    schedule 09.12.2009    source источник


Ответы (3)


Во-первых, вы можете упростить C++ до одного блока, если вашему комментарию поверят.

Итак, давайте сначала упростим на C++, не так ли?

if(some_condition_satisfied(g)) {
  a = eval(g); // never returns zero, right?
               // so we roll the next if block into this one
  do_something();
}

В clojure я бы попробовал

(if (some_condition_satisfied g)
    (let [a (eval g)]
         (do_something)))

Обратите внимание, что я устанавливаю a, но не использую его. Это то, что вы имели в виду? В противном случае передайте его в do_something или измените условие if

(if (and (some_condition_satisfied g) (not= 0 (eval g)))
    (do_something))

Это будет соответствовать коду C++ для

if ( some_condition_satisfied(g) && 0 != eval(g) ){
  do_something();
}

Кроме того, мой clojure заржавел, но я уверен, что проверил синтаксис.

person Ball    schedule 09.12.2009

Попробуй это:

(if-let [a (or (and (some-condition-satisfied g) 
                    (your-eval g))
               0)]
    (when (not= a 0)
       (do-something)))

Помните, что в clojure 0 является истинным, а не ложным, когда используется как логическое значение, поэтому некоторые идиомы C теряются при переводе. Я предполагаю, что clojure-версия некоторого условия-удовлетворения не возвращает 0, чтобы указать false, а вместо этого возвращает nil.

Мяч: вы забыли о части if(a!=0).

person Tim Schaeffer    schedule 09.12.2009
comment
Я это учитывал. В комментарии говорится, что eval(g) никогда не возвращает ноль. Единственные случаи, когда второй блок if будет пропущен, — это если либо комментарий ложный (возможно, может быть, даже вероятный), либо не удается выполнить some_condition_satisfied(g), а предыдущий блок if не присваивается a. Так что я чувствовал, что они могут быть объединены. - person Ball; 09.12.2009

Предполагая, что some_condition_satisfied является предикатом, your-eval-fn никогда не возвращает false и требуется значение a, вы также можете написать:

(if-let [a (and (some-condition-satisfied? g)
                (your-eval-fn g))]
  (do-something a))
person Hugo Duncan    schedule 09.12.2009