Clojure中look-sa​​y序列的解释

时间:2014-09-04 20:00:43

标签: clojure

这个功能如何运作?特别是,我在这里理解juxt的功能时遇到了问题。

(fn [s]
  (drop 1 (iterate (fn [s] 
                     (mapcat (juxt count first) 
                             (partition-by identity s))) s)))

1 个答案:

答案 0 :(得分:3)

这似乎是康威look-and-say sequence的生成器。

这会产生类似

的序列
(1)              ; there is 1 "1" here, so...
(1 1)            ; now there are 2 "1"s here, so...
(2 1)            ; now there is 1 "2" and 1 "1"
(1 2 1 1)        ; now there is 1 "1", 1 "2", and 2 "1"s, so...
(1 1 1 2 2 1)    ; now there are 3 "1"s, 2 "2"s, and 1 "1", so ...
(3 1 2 2 1 1)    ; etc.

drop 1从序列序列输出中删除输入序列,但由于它也正确地属于看起来顺序的序列,我们可能会删除它。

我们所拥有的是(iterate look-say initial-seq)其中

(defn look-say [s]
  (mapcat 
    (juxt count first) 
    (partition-by identity s)))

所有迭代都是重复输入函数的输出作为输入,产生一系列中间结果。

要了解look-sa​​y功能,请从内到外进行操作。让我们从上面示例输出的倒数第二行开始作为一个很好的例子。

(def s '(1 1 1 2 2 1))

我们想要连续重复分组

(def grouped-s (partition-by identity s))
grouped-s ;=>  ((1 1 1) (2 2) (1))

然后“说出”每组的计数

(map count grouped-s)
;=> (3 2 1)

但我们正在计算的是什么

(map first grouped-s)
;=> (1 2 1)

但我们宁愿同时获得计数和项目

(map (juxt count first) grouped-s)
;=> ([3 1] [2 2] [1 1])

几乎就在那里,只需要将所有这些连接在一起

(apply concat (map (juxt count first) grouped-s))
;=> (3 1 2 2 1 1)

相同
(mapcat (juxt count first) grouped-s)
;=> (3 1 2 2 1 1)

请注意,您也可以将其写为

(for [g (partition-by identity s)
      f [count first]] 
  (f g))
;=> (3 1 2 2 1 1)

可能更清楚或帮助解释前者。