如何在Clojure中实现For循环

nuv*_*vio 26 arrays loops for-loop clojure

我想在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...
}
Run Code Online (Sandbox Code Playgroud)

我是Clojure的初学者,这对我来说真的很复杂,但是我真的很想学习,因为我知道Clojure有很大的优势,比如使用refs ......

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

Jer*_*emy 37

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

(for [i (range 10)] (inc i))
Run Code Online (Sandbox Code Playgroud)

上述函数将返回从0到9加1,但是,似乎你只是想遍历顺序收集和利用每一个项目的所有号码.如果这就是您需要的全部内容,那么您不需要引用索引值,而是可以直接引用每个项目.

(for [d my-vec-of-data] (my-function d))
Run Code Online (Sandbox Code Playgroud)

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

(map my-function my-vec-of-data)
Run Code Online (Sandbox Code Playgroud)

双方mapfor返回由通过返回的值的值的集合my-function.这是因为Clojure的数据结构是不可变的,因此必须返回一个新的集合.如果这不是您需要的,或者您的功能有副作用,您可以使用doseq而不是for返回nil.

  • 我会自动增加吗? (2认同)

mik*_*era 34

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#)))
Run Code Online (Sandbox Code Playgroud)

用法如下:

(for-loop [i 0 (< i 10) (inc i)] 
  (println i))
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢在Clojure中如果你缺少一个语言功能,而不是等待它被添加到未来的版本,你可以自己编写. (33认同)