对于clojure中的循环

时间:2012-07-19 12:59:10

标签: for-loop clojure

    n = (count somevector)        
   (foo [w] ( for [i (range n) 
                   j (range w)
                   :let [n (* i j)] 
                   :while ( < i j)
                  ] 
              (println n)))

我跑的时候。

=&GT; (foo 10) ClassCastException clojurelangLazySeq无法投放到clojurelangIFn HelloWorld.core / foo

我真正想做的是有几个嵌套的for循环并且有一些ifs以及其他内部做一些检查。

编辑::

事实证明以下内容也会导致错误

(defn foo [arg]
 (      
      for [ i (range (count vector)) ]
      (
        for [j arg ]
        [i j]
        ) 

     ) ) 

IllegalArgumentException不知道如何创建ISeq:java.lang.Long clojure.lang.RT.seqFrom

编辑::

以下作品

(defn foo [arg]
  (def w arg) 
(for [ i (range (count vector)) ]
      (
        for [j (range v)  ]
        [i j]
        )
  )   )

现在有人可以帮助我理解为什么它首先不起作用?

3 个答案:

答案 0 :(得分:5)

如果您使用:whilefor-loop将返回null,因为第一个值为false,:when更好。

user=> (for [i (range 3) j (range 5)] [i j])
([0 0] [0 1] [0 2] [0 3] [0 4] [1 0] [1 1] [1 2] [1 3] [1 4] [2 0] [2 1] [2 2] [2 3] [2 4])
user=> (for [i (range 3) j (range 5) :while (< i j)] [i j])
()
user=> (for [i (range 3) j (range 5) :when (< i j)] [i j])
([0 1] [0 2] [0 3] [0 4] [1 2] [1 3] [1 4] [2 3] [2 4])

答案 1 :(得分:3)

  

不知道如何创建ISeq:java.lang.Long clojure.lang.RT.seqFrom

此错误消息准确说明了异常的原因。 我猜您通过long值,预计会有seq。 我可以重现它:

user> (def v [1 2 3])
#'user/v
user> (defn foo [arg]
        (for [ i (range (count v)) ]
             (for [j arg ]
                  [i j]))) 
#'user/foo
user> (foo (range 3))
(([0 0] [0 1] [0 2]) ([1 0] [1 1] [1 2]) ([2 0] [2 1] [2 2]))
user> (foo 3)
; Evaluation aborted.
; Don't know how to create ISeq from: java.lang.Long
;  [Thrown class java.lang.IllegalArgumentException]

您的foo功能有效。但是,arg参数必须是seq, 因为arg在嵌套forj

中绑定了

答案 2 :(得分:2)

你应该知道的第一件事是,clojure for不是for循环,而是list comprehension

这意味着,它用于使用指定的属性构建列表(实际上是惰性序列)。

您的原始for如下所示:

(for [i (range n) 
      j (range w)
      :let [n (* i j)] 
      :while ( < i j)] 
  (println n))

(我没有用原始示例获得类别转换异常)。

它的含义是:在i执行某些操作时,需要成对ji < j。第一对iji = 0j = 0。是0&lt; 0?不停。也就是说,你正在构建一个空序列。

现在,如果我们使用:while更改:when,则会将其含义更改为:对于每对ij,{ {1}},并与他们做点什么。也就是说,当你遇到i&gt; = j时,你不会停止构建序列,你只需跳过这一对。

接下来要注意的是i < j。此函数打印其参数,但始终返回println。此返回值是您在结果序列中获得的值,打印称为副作用。一般来说,你不希望有懒惰序列的副作用,因为它们(副作用)会在需要时发生。也就是说,如果将返回的序列分配给某个变量,则不会调用nil。当序列实现时,它们会弹出。

最重要的是,不要将println视为循环,将其视为序列构造函数。