Clojure中look-say序列的解释

Clojure中look-say序列的解释,clojure,Clojure,这个函数是如何工作的?特别是,我在理解这里的juxt功能时遇到困难 (fn [s] (drop 1 (iterate (fn [s] (mapcat (juxt count first) (partition-by identity s))) s))) 这似乎是康威的发电机 这会产生如下序列 (1) ; there is 1 "1" here, so... (1

这个函数是如何工作的?特别是,我在理解这里的
juxt
功能时遇到困难

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

这似乎是康威的发电机

这会产生如下序列

(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
从序列输出序列中删除输入序列,但由于该序列也正确地属于look-and-say序列,我们可能会删除它

然后我们得到的是
(迭代查看并说出初始seq)
在哪里

(defn look-say [s]
  (mapcat 
    (juxt count first) 
    (partition-by identity s)))
iterate所做的就是将函数的输出作为输入重复输入,生成一系列中间结果

要理解look-say函数,请从内到外进行操作。让我们从上面示例输出的下一行开始,这是一个很好的示例

(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)
哪一个可能更清楚或者有助于解释前者