Clojure中的数组和循环

Ann*_*nna 2 clojure

我正在尝试学习编程语言Clojure.我很难理解它.我想尝试实现像这样简单的东西(例如):

int[] array = new int[10];
array[0] =1; 
int n = 10; 

for(int i = 0; i <= n; i++){
    array[i] = 0; 
}
return array[n]; 
Run Code Online (Sandbox Code Playgroud)

由于我是Clojure的新手,我甚至不了解如何实现这一点.如果有人可以解释或给出类似数组/ for循环在Clojure中如何工作的示例,那将会非常有用.我试过做一些研究,但至于我的理解,Clojure并没有真正的for循环.

Car*_*ate 6

我认为,在@李的回答的最后一点应大力强调.

除非出于性能原因绝对需要数组,否则你应该在这里使用向量.一旦开始使用本机Clojure结构,整个代码块就会变得微不足道:

; Create 10 0s, then put them in a vector
(vec (repeat 10 0))
Run Code Online (Sandbox Code Playgroud)

vec 如果你可以使用惰性序列而不是严格的向量,你甚至可以跳过调用.

还应注意,尽管将元素预初始化为0是不必要的.与数组不同,向量是可变长度的; 它们可以在创建后添加和扩展.只需要一个空矢量并根据需要添加元素就更清晰了.


Dav*_*ann 6

编写for您编写的Java 循环的Clojure方法是首先考虑为什么循环。有很多选项可将Java循环移植到Clojure。在其中选择取决于您的目标。

十个零的方法

如《致死遗体》所述,如果您需要在集合中包含十个零,请考虑:

(repeat 10 0)
Run Code Online (Sandbox Code Playgroud)

返回一个序列(一个懒惰序列),这在Clojure中很常见,用于处理顺序值。如果相反需要通过索引访问十个零,则将它们放在具有以下内容的向量中:

(vec (repeat 10 0))
Run Code Online (Sandbox Code Playgroud)

要么

(into [] (repeat 10 0))
Run Code Online (Sandbox Code Playgroud)

或者,您可以直接在代码中编写向量文字:

[0 0 0 0 0 0 0 0 0 0]
Run Code Online (Sandbox Code Playgroud)

并且,如果由于某种原因特别需要Java数组,则可以使用to-array

(to-array (repeat 10 0))
Run Code Online (Sandbox Code Playgroud)

但是请记住Clojure参考文档中有关Java interop的建议

Clojure支持Java数组的创建,读取和修改[但是]建议您限制使用数组以与需要它们作为参数或将它们用作返回值的Java库进行互操作。

这些文档列出了一些主要用于Java互操作或“支持变异或更高性能的操作”时使用Java数组的功能。在几乎所有情况下,Clojurists都只使用向量。

循环播放Clojure

如果您正在做除产生十个零以外的其他事情怎么办?Clojure的“循环”方式取决于您的需求。

您可能需要递归,为此Clojure具有loop/ recur

(loop [x 10]
  (when-not (= x 0)
    (recur (- x 2))
Run Code Online (Sandbox Code Playgroud)

您可能需要计算的值用于在收集一些(一个或多个)的每一个值:

(for [x coll])
  (calculate-y x))
Run Code Online (Sandbox Code Playgroud)

您可能需要遍历多个集合,类似于Java中的嵌套循环:

(for [x ['a 'b 'c] 
      y [1 2 3]]
  (foo x y))
Run Code Online (Sandbox Code Playgroud)

如果您只需要多次产生副作用,则反复出现卡塞现象:

(repeatedly 10 some-fn)
Run Code Online (Sandbox Code Playgroud)

如果您需要为集合中的每个值产生副作用,请尝试以下剂量q

(doseq [x coll]
  (do-some-side-effect! x))
Run Code Online (Sandbox Code Playgroud)

如果您需要对整数范围产生副作用,则可以这样使用doseq

(doseq [x (range 10)] 
  (do-something! x))
Run Code Online (Sandbox Code Playgroud)

...但是dotimes就像doseq一个内置范围

(dotimes [x 9] 
  (do-something! x))
Run Code Online (Sandbox Code Playgroud)

Clojure函数甚至比那些循环构造更普遍,它为集合中的每个元素(例如map及其亲戚)产生一个值,或者出于特殊目的(例如filterremove)或为了创建一些新值或集合(例如,reduce)。