的问题
我需要创建,鉴于潜在的无限序列的有限序列时,它产生是他们的“笛卡尔积”的序列的功能。潜在的无限序列的有限序列的笛卡尔乘积
即给定的顺序
'((1 2) (3 4))
功能产生(的某种排序):
'((1 3) (1 4) (2 3) (2 4)
重要,为每一位p
在笛卡尔积ps
名单,必须有一些自然数n
,例如(= p (last (take n ps)))
。或者,非正式地说,您只需要遍历有限数量的序列以到达其中的任何元素。
这个条件在处理无限列表时变得很重要。在Haskell
在Haskell
解决方案,这是我会怎么做它:
interleave :: [a] -> [a] -> [a]
interleave [] ys = ys
interleave (x:xs) ys = x : interleave ys xs
combine :: [[a]] -> [[a]]
combine = foldr prod [[]]
where
prod xs css = foldr1 interleave [ [x:cs | cs <- css] | x <- xs]
,把它你会得到如下:Clojure中
combine [[0..] [0..]] = [[0,0,0],[1,0,0],[,1,0],[2,0,0],[0,0,1],[1,1,0],...
解决方案
所以我试图在Clojure中复制它,就像这样(这几乎是一个直接的t ranslation):
(defn interleave
"Returns a lazy sequence of the interleavings of sequences `xs` and `ys`
(both potentially infinite), leaving no elements discarded."
[xs ys]
(lazy-seq
(if-let [[x & xs*] (seq xs)]
(cons x (interleave ys xs*))
ys)))
(defn interleave*
"Converts a sequence of potentially infinite sequences into its lazy
interleaving."
[xss]
(lazy-seq
(when-let [[xs & xss*] (seq xss)]
(interleave xs (interleave* xss*)))))
(defn combine
"Takes a finite sequence of potentially infinite sequences, and combines
them to produce a possibly infinite sequence of their cartesian product."
[xss]
(if-let [[xs & xss*] (seq xss)]
(interleave*
(for [x xs]
(for [cs (combine xss*)]
(lazy-seq (cons x cs)))))
'(())))
但是当我运行:
(take 1 (combine [(range) (range)]))
我得到:
StackOverflowError cfg.util/combine/iter--3464--3468/fn--3469/fn--3470/iter--3471--3475/fn--3476
所以,我怎么让它偷懒足够,以免造成堆栈溢出?真的,我不明白Clojure的惰性序列模型是如何工作的,这是主要问题。
你是对的,因为序列到达[100 10]所需的时间是不合理的。然而,这不是因为重复的工作,而是因为排序:在'interleave *'的定义中使用本质上折叠在列表上的东西给最后一个给予'combine'的集合带来了偏见:该集合中的数字上升指数级地比第一次收集快。例如,'[10 100]'会比'[100 10]'快得多。尽管如此,您的解决方案确实很好,但我完全无法理解它。 – amnn 2014-09-28 20:18:47
@asQuirreL。啊!相反,正如你可能已经收集到的,我很难理解你的解决方案:)。我的收益平均通过所有收藏品 - 有点像康托尔列举的理性。理解它的方法是返回几个例子的'entries',然后在'seens'旁边看看它们。一旦构建了“条目”序列,它就会驱动剩下的过程。 – Thumbnail 2014-09-28 20:40:54
我想我只是想把你的解决方案包裹起来。我也相信自己也穿越了整个空间,而且相当容易(如果不是n维的话),通过连续向上移动一个维度,对吗?这是很不错的。为了记录,我给出的解决方案速度大约快两倍,如果您不在意它会产生偏见的样本。然而,我很在乎,所以这看起来很有希望。非常感谢! – amnn 2014-09-28 21:09:46