如何在Clojure中实现For循环?

时间:2020-12-07 22:50:54

I'd like to implement this little code in Clojure, but I am struggling:

我想在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...
}

I am a beginner with Clojure and it's really complicated for me to do something simple like this, but I am really trying to learn as much as possible as I know that there are great advantages with Clojure such as using refs...

我是Clojure新手,做这样简单的事情真的很复杂,但我真的在尽可能多地学习Clojure的好处,比如使用refs……

I would really appreciate it if somebody could help me. Thanks!!

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

2 个解决方案

#1


34  

One way to translate an imperative for loop to Clojure is to use the for macro.

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

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

The above function will return all the numbers from 0 to 9 incremented by 1. However, it appears you simply want to iterate over a sequential collection and use each item. If that's all that you need, then you don't need to reference an index value, instead you can reference each item directly.

上面的函数将返回从0到9加1的所有数字。但是,看起来您只是希望遍历顺序集合并使用每个项。如果这就是您所需要的,那么您不需要引用索引值,而是可以直接引用每个项。

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

However, for this simple case, the map function would probably be a better choice because it is designed to invoke functions with arguments from collections. The following example is equivalent to the use of for above.

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

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

Both map and for return a collection of values made up of the values returned by my-function. This is because Clojure's data structures are immutable, so it's necessary to have a new collection returned. If that isn't what you need or if your function has side effects, you could use doseq instead of for, which returns nil.

map和for返回由my-function返回的值组成的值集合。这是因为Clojure的数据结构是不可变的,所以需要返回一个新的集合。如果这不是你需要的或者如果你的函数有副作用,你可以使用doseq而不是for,它返回nil。

#2


33  

Jeremy's answer is good for how to do a for loop in idiomatic Clojure.

杰里米的回答对如何在惯用的Clojure中执行for循环很有帮助。

If you really want an imperative-style for loop in Clojure, you can create one with this macro:

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

(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#)))

Usage as follows:

用法如下:

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

#1


34  

One way to translate an imperative for loop to Clojure is to use the for macro.

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

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

The above function will return all the numbers from 0 to 9 incremented by 1. However, it appears you simply want to iterate over a sequential collection and use each item. If that's all that you need, then you don't need to reference an index value, instead you can reference each item directly.

上面的函数将返回从0到9加1的所有数字。但是,看起来您只是希望遍历顺序集合并使用每个项。如果这就是您所需要的,那么您不需要引用索引值,而是可以直接引用每个项。

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

However, for this simple case, the map function would probably be a better choice because it is designed to invoke functions with arguments from collections. The following example is equivalent to the use of for above.

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

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

Both map and for return a collection of values made up of the values returned by my-function. This is because Clojure's data structures are immutable, so it's necessary to have a new collection returned. If that isn't what you need or if your function has side effects, you could use doseq instead of for, which returns nil.

map和for返回由my-function返回的值组成的值集合。这是因为Clojure的数据结构是不可变的,所以需要返回一个新的集合。如果这不是你需要的或者如果你的函数有副作用,你可以使用doseq而不是for,它返回nil。

#2


33  

Jeremy's answer is good for how to do a for loop in idiomatic Clojure.

杰里米的回答对如何在惯用的Clojure中执行for循环很有帮助。

If you really want an imperative-style for loop in Clojure, you can create one with this macro:

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

(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#)))

Usage as follows:

用法如下:

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