如何在Clojure中实现For循环

时间:2012-04-02 18:39:55

标签: arrays loops clojure for-loop

我想在Clojure中实现这个小代码,但我很挣扎:

struct mystruct {
   int id;
   int price;
};

mystruct mydata[10];

for (int i=0; i<10; i++) {
  myfunction(mydata[i].id, mydata[i].price);
  //other things...
}

我是Clojure的初学者,我做这样简单的事情真的很复杂,但我真的很想学习,因为我知道Clojure有很大的优势,比如使用refs ......

如果有人能帮助我,我真的很感激。谢谢!

3 个答案:

答案 0 :(得分:36)

将循环命令转换为Clojure的一种方法是使用for宏。

(for [i (range 10)] (inc i))

上面的函数将返回0到9之间的所有数字,加1。但是,您似乎只想迭代顺序集合并使用每个项目。如果这就是您需要的全部内容,那么您不需要引用索引值,而是可以直接引用每个项目。

(for [d my-vec-of-data] (my-function d))

但是,对于这个简单的情况,map函数可能是更好的选择,因为它被设计为使用来自集合的参数调用函数。以下示例相当于使用上面的for

(map my-function my-vec-of-data)

mapfor都会返回由my-function返回的值组成的值集合。这是因为Clojure的数据结构是不可变的,因此必须返回一个新的集合。如果这不是您所需要的,或者您的功能有副作用,则可以使用doseq代替for,而nil会返回{{1}}。

答案 1 :(得分:33)

Jeremy的答案对于如何在惯用的Clojure中进行for循环很有用。

如果你真的想在Clojure中使用命令式样式for循环,你可以用这个宏创建一个:

(defmacro for-loop [[sym init check change :as params] & steps]
 `(loop [~sym ~init value# nil]
    (if ~check
      (let [new-value# (do ~@steps)]
        (recur ~change new-value#))
      value#)))

用法如下:

(for-loop [i 0 (< i 10) (inc i)] 
  (println i))

答案 2 :(得分:1)

doseq 的作用类似于 for-loop 用法:

(doseq [i (for [i (range 10)] (inc i))]
    (println "i=" i))

绑定类似于Clojure中的for。但是,它不会通过评估 doseq 内的表达式来返回列表。它为序列中的每个值执行表达式并返回 nil

要循环一个 seq,您可以简单地使用:

(doseq [value list]
    (println "Your expression here" value)