[英]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
做某事时,取i
和j
对。 The first pair of i
and j
is i = 0
and j = 0
. i
和j
的第一对是i = 0
和j = 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
,则会将含义更改为:对于i
和j
每对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.