简体   繁体   English

在Clojure中循环

[英]For loop in clojure

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

When i run it. 当我运行它。

=> (foo 10) ClassCastException clojure . =>(foo 10) ClassCastException clojure lang . lang LazySeq cannot be cast to clojure . LazySeq不能转换为clojure lang . lang IFn HelloWorld.core/foo IFn HelloWorld.core / foo

What I am really looking to do is have a couple of nested for loops and have some ifs and else inside it do some checking. 我真正想要做的是有几个嵌套的for循环,并有一些ifs,否则在其中进行一些检查。

Edit :: 编辑::

As it turns out the following also causes error 事实证明,以下内容也会导致错误

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

     ) ) 

IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom IllegalArgumentException不知道如何从以下位置创建ISeq:java.lang.Long clojure.lang.RT.seqFrom

Edit:: 编辑::

the following works 以下作品

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

Now can someone help me understand why would it not work in the first place ? 现在有人可以帮助我理解为什么一开始它不起作用吗?

if you use :while , for-loop will return null, because first value is false, :when is better. 如果使用:while ,则for-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])

Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom 不知道如何从以下位置创建ISeq:java.lang.Long clojure.lang.RT.seqFrom

This error message states the cause of exception accurately. 此错误消息准确地指出了异常原因。 I guess you passed a long value where a seq is expected. 我猜您传递了一个long值,该值应该是seq I could reproduce it: 我可以复制它:

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]

Your foo function works. 您的foo函数有效。 However, the arg argument must be a seq , because arg is binded in the nested for to j 然而, arg参数必须是一个seq ,因为arg在嵌套绑定for ,以j

The first thing you should know is, that clojure's for is not a for loop, it's a list comprehension . 您应该知道的第一件事是clojure的for不是for循环,而是列表理解

This means, that it is used to build lists (lazy sequence, actually) with the specified properties. 这意味着,它用于构建具有指定属性的列表(实际上是延迟序列)。

Your original for looks like this: 您原来for这个样子的:

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

(I don't get a class cast exception with your original example). (您的原始示例没有类强制转换异常)。

What it says is: take pairs of i and j while i < j do something. 它的意思是:当i < j做某事时,取ij对。 The first pair of i and j is i = 0 and j = 0 . ij的第一对是i = 0j = 0 Is 0 < 0? 是0 <0吗? No. Stop. 不停。 That is, you're constructing an empty sequence. 也就是说,您正在构造一个空序列。

Now, if we change the :while with :when , it'll change the meaning to: for each pair of i and j , for which i < j , and do something with them. 现在,如果我们用:when更改:while ,则会将含义更改为:对于ij每对i < j ,并对其进行处理。 That is, you won't stop constructing the sequence when you encounter an i >= j, you'll just skip this pair. 也就是说,当您遇到i> = j时,您不会停止构建序列,只是跳过了这一对。

The next thing to note is the println . 接下来要注意的是println This function prints its arguments, but always returns nil . 该函数输出其参数,但始终返回nil This return value is what you'll get in the result sequence and the printing is called a side effect. 此返回值是您将在结果序列中获得的值,打印称为副作用。 Generally, you don't want side effect with lazy sequences, because they (the side effects) will happen when needed. 通常,您不希望延迟序列产生副作用,因为它们会在需要时发生(副作用)。 That is, if you assign the returned sequence to some variable, none of the println s will be called. 也就是说,如果将返回的序列分配给某个变量,则不会调用任何println They'll start popping up, when the sequence gets realized . 当序列实现时,它们将开始弹出。

The bottom line is, don't think of for as a loop, think of it as a sequence constructor. 最重要的是,不要将for视为循环,而应将其视为序列构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM