首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用闭包重述混淆参数计数错误

使用闭包重述混淆参数计数错误
EN

Stack Overflow用户
提问于 2018-04-11 03:47:05
回答 3查看 263关注 0票数 2

我想要一个函数,它以循环的方式接收集合并返回元素。即:

代码语言:javascript
复制
 (round-robin [[:a1 :a2 :a3] [:b1] [:c1 :c2][)
 ;; => (:a1 :b1 :c1 :a2 :c2 :a3)

有用的东西:

代码语言:javascript
复制
(defn round-robin [all-colls]
    (let [colls (filter seq all-colls)]
         (if (seq colls)
             (lazy-cat
                (map first colls)
                (round-robin (map next colls))))))  ;; recursive call

我会感兴趣的一个更好的成语,但这花了我一段时间来提出,因为我不明白为什么这将不能与复发。例如:

代码语言:javascript
复制
 (defn round-robin [all-colls]
    (let [colls (filter seq all-colls)]
         (if (seq colls)
             (lazy-cat
                (map first colls)
                (recur (map next colls))))))  ;; same with recur
 java.lang.IllegalArgumentException: Mismatched argument count to recur, expected: 0 args, got: 1

为什么说预期的args是0?

请注意,如果我尝试使用loop ... recur,则会得到相同的错误。也许与镜中的讨论的重复有关(我不太觉得),或者懒惰的猫是一个重复的目标?

只是不明白为什么没有这样的版本可以重复使用。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-04-11 04:34:47

之所以会发生这种情况,是因为对lazy-seq的调用扩展到不是recur0-度函数。,而是递归到lazy-seq ( lazy-cat使用的)扩展到的函数中。宏在这里的使用使事情变得复杂。

如果你写:

代码语言:javascript
复制
(lazy-seq (recur))

这个(大致)转化为:

代码语言:javascript
复制
(LazySeq. (fn [] (recur)))

注意现在实际发生了什么函数recur

此外,正如@leetwinski所指出的,recur不在尾部位置,因此无论如何都无法优化这个递归。如果您查看lazy-cat的docs,您将看到描述宏如何展开的以下等式:

代码语言:javascript
复制
(lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))

在您的例子中,recur基本上是zs。它在形状内,在尾部位置,但不是在位置本身。

只需直接调用函数,而不是使用recur。由于lazy-seq的工作方式,这不会导致堆栈溢出。

票数 2
EN

Stack Overflow用户

发布于 2018-04-11 06:29:13

此外:您可以让循环懒散,只需以一种功能的方式操作集合:

代码语言:javascript
复制
(defn round-robin [data]
  (->> data
       (filter seq)
       (iterate (partial keep next))
       (take-while seq)
       (mapcat (partial map first))))
#'user/round-robin

user> (round-robin [[:a1 :a2 :a3] [:b1] [:c1 :c2]])
;;=> (:a1 :b1 :c1 :a2 :c2 :a3)

user> (round-robin [[] []])
;;=> ()

user> (round-robin [])
;;=> ()
票数 3
EN

Stack Overflow用户

发布于 2018-04-11 04:35:04

这并不明显,但答案是:

代码语言:javascript
复制
(def data [[:a1 :a2 :a3] [:b1] [:c1 :c2]])
(defn round-robin [data-seqs]
  (let
    [lengths   (for [s data-seqs] (count s))
     limit     (apply max lengths)
     coll-seqs (for [s data-seqs]
                 (take limit (concat s (repeat nil))))
     matrix    (apply map vector coll-seqs)
     keepers   (filter not-nil? (flatten matrix))
     ]
    (vec keepers)))

取得的成果:

代码语言:javascript
复制
lengths => (3 1 2)
limit => 3
coll-seqs => ((:a1 :a2 :a3) (:b1 nil nil) (:c1 :c2 nil))
matrix => ([:a1 :b1 :c1] [:a2 nil :c2] [:a3 nil nil])
keepers => (:a1 :b1 :c1 :a2 :c2 :a3)
(round-robin data) => [:a1 :b1 :c1 :a2 :c2 :a3]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49766189

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档