了解Clojure代码的执行流程

Ful*_*nal 0 clojure

我现在正在学习 Clojure,我来自命令式编程,所以我在理解该代码的执行流程时遇到了问题:

(defn chop-chop [coll]

  (let [x (partition-by identity coll)]

    (map list (map (comp str first) x)

                (map count x))))

=> (chop-chop "aaaabbbcca")

=> (("a" 4) ("b" 3) ("c" 2) ("a" 1))
Run Code Online (Sandbox Code Playgroud)

我明白我们:

  1. 在此处创建带有参数 coll 的函数chop-chop

  2. 然后我们为 coll 应用函数 partition-by,但我不确定身份是什么

  3. 接下来我们将之前操作的结果绑定到 x

  4. 但我无法理解下一行代码:

(map list (map (comp str first) x)
    (map count x))))
Run Code Online (Sandbox Code Playgroud)

有人可以向我解释该程序的逐步执行流程吗?非常感谢!

Aar*_*ell 5

jist

这个例子:

  1. 获取一个集合(在本例中为一个字符串)
  2. 获取重复字母组
  3. 在组上映射以获得代表信
  4. 映射组以获取每个组的计数
  5. 映射 #3 和 #4 以获取键值元组、字母及其重复次数(对于本例而言,并非所有时间)。

jist+

关于你的四颗子弹:

  1. 是的,它是一个用defn宏定义的单元函数
  2. 是的,并identity返回参数
;; Possible values: 1, :a, #(+ 1 2), {:a [1 2]}
(identity 1) ;;=> 1
(identity :a) ;;=> :a
(identity #(+ 1 2)) ;;=> #function[boop.core/eval7764/fn--7765]
(identity {:a [1 2]}) ;;=> {:a [1 2]}

(partition-by identity "aaaabbbcca") ;;=> (\a \a \a \a) (\b \b \b) (\c \c) (\a))
Run Code Online (Sandbox Code Playgroud)

以防万一您不了解 partition-by,它会在每次函数值更改时创建一个新组。#(< 3 %)false用于12。由于结果相同,因此将它们分组在一起。3 4 5将具有相同的结果,因此它们将组合在一起。

;; f
;; =
;; number?

;; coll
;; [1 2 3 4 5]
;; [:a :b '(:Yo) 3]

;; f1 coll1
(partition-by #(= 3 %) [1 2 3 4 5]) ;;=> ((1 2) (3) (4 5))
;; f1 coll2
(partition-by #(= 3 %) [:a :b '(:Yo) 3]) ;;=> ((:a :b (:Yo)) (3))
;; f2 coll1
(partition-by number? [1 2 3 4 5]) ;;=> ((1 2 3 4 5))
;; f2 coll2
(partition-by number? [:a :b '(:Yo) 3]) ;;=> ((:a :b (:Yo)) (3))
Run Code Online (Sandbox Code Playgroud)
  1. 是的,您将之前的操作绑定到x. 这个例子映射了两个 map,所以如果他们将两个 map 绑定到 variables 会更清楚
(defn chop-chop [coll]

  (let [x (partition-by identity coll)
        ;; Could bind the two maps here
        first-letter-map (map (comp str first) x)
        repeating-letter-count (map count x)]
    ;; a map of maps
    (map list first-letter-map repeating-letter-count)))

(chop-chop "aaaabbbcca") ;;=> (("a" 4) ("b" 3) ("c" 2) ("a" 1))
Run Code Online (Sandbox Code Playgroud)
  1. 在最后一点代码:

地图可以映射一个或多个集合。

这是每张地图的一个集合:

;; maps
;; (map (comp str first) x)
;; (map count x)

;; coll
;; [["woo" "yes"] ["hello" "world"]]
;; ((\a \a \a \a) (\b \b \b) (\c \c) (\a)), the result of (partition-by identity "aaaabbbcca")

;; m1 c1
(map (comp str first) [["woo" "yes"] ["hello" "world"]]) ;;=> ("woo" "hello")
;; m1 c2
(map (comp str first) '((\a \a \a \a) (\b \b \b) (\c \c) (\a))) ;;=> ("a" "b" "c" "a")
;; m2 c1
(map count [["woo" "yes"] ["hello" "world"]]) ;;=> (2 2)
;; m2 c2
(map count '((\a \a \a \a) (\b \b \b) (\c \c) (\a))) ;;=> (4 3 2 1)
Run Code Online (Sandbox Code Playgroud)

这是每张地图的两个集合:

;; function
;; #(str (first %1) (first %2))
;; #(list (count %1) (count %2))

;; same colls, but passed in at the same time
;; [["woo" "yes"] ["hello" "world"]]
;; ((\a \a \a \a) (\b \b \b) (\c \c) (\a)) 

(def c1 [["woo" "yes"] ["hello" "world"]])
(def c2 '((\a \a \a \a) (\b \b \b) (\c \c) (\a)))

(map #(str (first %1) (first %2)) c1 c2) ;;=> ("wooa" "hellob")
(map #(list (count %1) (count %2)) c2 c1) ;;=> ((4 2) (3 2))
Run Code Online (Sandbox Code Playgroud)

你还应该明白comp

;; comp vs. personall const
;; (comp str first)
;; #(str (first %))

;; seq
;; [\a "Wow"]
;; [132 :a]

;; c1 s1
((comp str first) [\a "Wow"]) ;;=> "a"
;; c2 s1
(#(str (first %)) [\a "Wow"]) ;;=> "a"
;; c1 s2
((comp str first) [132 :a]) ;;=> "132"
;; c2 s2
(#(str (first %)) [132 :a]) ;;=> "132"
Run Code Online (Sandbox Code Playgroud)

欢迎来到 Clojure 社区!