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

当我运行它时。

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

我真正想做的是有几个嵌套的 for 循环,并有一些 if 和 else 在里面做一些检查。

编辑 ::

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

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

     ) ) 

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

编辑::

以下作品

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

现在有人可以帮我理解为什么它一开始就不起作用吗?

4

3 回答 3

7

如果使用: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])
于 2012-07-19T13:24:17.863 回答
3

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

此错误消息准确地说明了异常的原因。我猜你在预期的地方传递了一个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参数必须是 a seq,因为arg绑定在嵌套forj

于 2012-07-19T14:15:40.073 回答
3

您应该知道的第一件事是,clojurefor不是 for 循环,而是列表理解

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

您的原件for如下所示:

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

(我的原始示例没有出现类转换异常)。

它说的是:采取成对的ij同时i < j做某事。第一对iandji = 0and j = 0。0 < 0 吗?不停。也就是说,您正在构建一个空序列。

现在,如果我们改变:whilewith :when,它的含义会改变为:对于每一对iand j,对于 which i < j,并且对它们做一些事情。也就是说,当你遇到 i >= j 时,你不会停止构建序列,你会跳过这对。

接下来要注意的是println. 这个函数打印它的参数,但总是返回nil。此返回值是您将在结果序列中获得的值,打印称为副作用。通常,您不希望惰性序列产生副作用,因为它们(副作用)会在需要时发生。也就是说,如果将返回的序列分配给某个变量,println则不会调用任何 s。当序列实现时,它们将开始弹出。

底线是,不要将for其视为循环,将其视为序列构造函数。

于 2012-07-20T07:12:28.523 回答