Clojure:if 中的多个任务

bud*_*mer 2 if-statement clojure

据我所知, if 的形式是(if [condition] [true] [false])。同样, cond 是(cond [condition] [true] ... [condition] [true] [false])。每个真假段似乎只接受一个动作。如果我想代表以下逻辑:

if (i > 0)
{
    a += 5;
    b += 10;
}
Run Code Online (Sandbox Code Playgroud)

我想我必须这样做:

(if (> i 0) (def a (+ a 5)))
(if (> i 0) (def b (+ b 10)))
Run Code Online (Sandbox Code Playgroud)

这样第二个动作就不会被混淆为错误的结果。这是它需要的方式,还是有办法为 if 创建更大的主体?

ps 我也怀疑每次重新定义 a 和 b 不是增加的最佳方法,但也没有看到不同的方法。使用 conj 时,我还必须重新定义列表。

gfr*_*cks 5

使用原子而不是 vars ( def)的最直接的事务是

;; assuming something like (def a (atom 0)) (def b (atom 0))
(if (> i 0)
  (do
    (swap! a + 5)
    (swap! b + 10)))
Run Code Online (Sandbox Code Playgroud)

或者

(when (> i 0)
  (swap! a + 5)
  (swap! b + 10))
Run Code Online (Sandbox Code Playgroud)


Thu*_*ail 5

你正在通过望远镜的错误一端进行观察。请记住

  • Clojure 没有局部变量。
  • Clojure 没有操作(通常称为语句),只有返回值的表达式。

Clojure中没有与语句等效的语句a += 5;

然而,表达式可能会产生副作用:print诸如此类的东西不会起到任何其他作用。该do表单允许您在返回最终值之前完成一系列副作用。例如,

(do (print a) (print b) (+ a b))
Run Code Online (Sandbox Code Playgroud)
  • 印刷a
  • 印刷b
  • 返回它们的总和。

这就是为什么,当你写表格时if......

每个真假段似乎只接受一个动作。

Clojure 所具有的是

  • 本地名称绑定,let形式为 和
  • letCalled的派生版本loop,实现了递归的原始形式,可以替代 C 或 Java 等语言中循环的简单使用。

let在它们及其后代之间,loop您可以编写最简单的控制结构。确定这是否适用于您的程序片段......

if (i > 0)
{
    a += 5;
    b += 10;
}
Run Code Online (Sandbox Code Playgroud)

...我们必须查看上下文。

然而,这是 C 中的最大公约数函数(未经测试)

long gcd (long i, long j)
{
  long m = i, n = j;
  while (n != 0)
  {
    long t = n;
    n = m % n;
    m = t;
  }
}
Run Code Online (Sandbox Code Playgroud)

在 Clojure 中

(defn gcd [i j]
  (loop [m i, n j]
    (if (zero? n)
      m
      (recur n (mod m n)))))
Run Code Online (Sandbox Code Playgroud)

这两个都可以缩写。