我对Clojure很新。我有一个Java方法,包括一个布尔变量,我想重写这个方法,以便在Clojure中使用相同的功能。但我无法在Clojure中找到如何在运行时设置布尔值true和false。
以下片段基本上只强调布尔部分。我很难想到以函数方式编写它。
int calculate(...){
int y = 0;
boolean flag = false;
foreach(...){
if(!flag){
y = 1;
flag = true;
}
else{
y = -1;
flag = false;
}
}
return y;
}
这是我在Clojure的第一次尝试:
(defn calculate [...]
( ??flag?? -> I do not know which macro I should use over here
(doseq [x ...]
(if (false? flag) (do 1 (set the flag true))
(do -1 (set the flag false)))))
如何在Clojure中实现相同的概念?
答案 0 :(得分:7)
对于您拥有的Java代码,将其转换为Clojure的最简单方法是跳过所有迭代并返回最终值:
(defn calculate [coll]
(odd? (count coll)))
如果你想要更精细的东西,我猜你可以做类似
的事情(defn calc [coll flag]
(if (empty? coll)
flag
(recur (rest coll) (not flag))))
并用
调用它(defn calculate [coll]
(calc coll false))
这种递归不是最惯用的风格,而且对于这个问题它有点疯狂,但它演示了如何改变变量而不是变量,而是编写一个表达式,当被评估时产生传入的值下一次迭代(参见上例中的重复调用)。
将
重写为更好的风格(defn calculate
([coll flag]
(if (empty? coll)
flag
(recur (rest coll) (not flag))))
([coll]
(calculate coll false)))
所以只有一个功能名称需要处理。 (我离开了另一个方向,认为对于Clojure的新人来说可能会更清楚。)
我的评论第二,建议您查看4clojure。这是一种很好的练习方式,一旦你有了解决方案,你就可以从其他用户那里学习。
答案 1 :(得分:2)
使用loop
/ recur
模拟Clojure中的迭代语句:
(defn calculate [...]
(loop [...
y 0
flag false]
...
(if (false? flag)
(recur ... 1 true) ;; "loop with x = ..., y = 1 and flag = true"
(recur ... -1 false)) ;; "loop with x = ..., y = -1 and flag = false"
... )
编辑:让我详细说明。我从您的问题中理解的是,您无法将基于可变性(Java)的代码转换为Clojure。这很自然。 Clojure在不变性方面很重要。
在Clojure程序中实现可变性的一种方法是使用引用类型,特别是atoms。你的代码片段可以用Clojure编写:
(defn calculate [...]
(let [y (atom 0)
flag (atom false)]
(doseq [x ...]
(if (false? @flag)
(do (reset! y 1)
(reset! flag true))
(do (reset! y -1)
(reset! flag false))))
(... return some function of y and flag ...)))
有效。但是,在Clojure中,大量使用原子和副作用并不是惯用的;虽然有用,但是,与功能性的,惯用的Clojure相比,并不是必需和麻烦。
在迭代上下文中建模可变性的一种更好的方法是在递归方面对其进行转换,就像我对上面的loop
/ recur
所做的那样。