我试图在Clojure中弄清楚这个Java的等价物:
public int compute(int x) {
if (x < 0) return 0;
// continue do some computing
return result;
}
是否有惯用的Clojure在函数中“中断”处理并返回结果?
答案 0 :(得分:5)
使用Clojure进行编程时,其中一个主要的指导原则是,所有东西都“返回”一个值,尽管它通常表示为“一切都评估为某种东西”。调用函数时,函数的结果是函数中最后一个表达式的结果。
user> (defn foo [] 1 2 3 4)
#'user/foo
user> (foo)
4
有几种形式表达“早退”的想法:
user> (defn compute [x] (cond (< x 0) 0 :default (* x 42)))
#'user/compute
user> (compute 1)
42
或
user> (defn compute [x] (if-let [y (< x 0)] (* 8 y) (* 4 x)))
#'user/compute
user> (compute 1)
4
或简单的if
表达式。重要的概念是一切都会带来新的价值。这在clojure社区中产生了许多口号,包括“价值导向编程”
答案 1 :(得分:3)
没有。没有短路return
声明(或break
或goto
...)。回归是隐含的。
在你的例子中,与Clojure相近的是
(defn test [x]
(if (< x 0)
0
(let [result (comment compute result)]
result)))
但你可能会在没有命名的情况下返回result
:
(defn test [x]
(if (< x 0)
0
(comment compute result)))
这些运行,但comment
始终评估为nil
。
顺便说一下,如果测试失败,带有两个表达式(而不是完整三个)的if
构造会返回nil
。
(if (< 3 0) 0) ; nil
所以总会有回归的东西。
答案 2 :(得分:2)
Clojure没有这样的return语句,但是你可以通过在if语句上使用一个非常简单的代码分支来实现类似的结果。
(defn compute [x]
(if (< x 0) 0
(do ...
result)))
您也可以使用cond
或monad来做类似的事情。
答案 3 :(得分:2)
你真的需要指定:
// continue do some computing
一个例子..
public int test(int x) {
if (x < 0)
return 0;
int tmp = getSomthing1(x);
int tmp2 = getSomething2(x, tmp);
int result = tmp/tmp2;
return result;
}
这就像是:
(defn test [x]
(if (< x 0)
0
(let [tmp (getSomthing1 x)
tmp2 (getSomething2 x tmp)]
(/ tmp tmp2))))
您所拥有的是(if predicate consequent alternative)
,而let
可以保留中间计算而无需强制执行代码。