我是Clojure的新手,我尝试使用clojuredocs.org中的示例数据。
;; Data
(def scenes [{:subject "Frankie"
:action "say"
:object "relax"}
{:subject "Lucy"
:action "loves"
:object "Clojure"}
{:subject "Rich"
:action "tries"
:object "a new conditioner"}])
(defn play [scenes n]
"Play a scene"
(->>
scenes
(#(get % n))
((juxt :subject :action :object))
(interpose " ")
(apply str)))
play
功能正常工作:
my-stuff.core> (play scenes 0)
"Frankie say relax"
my-stuff.core> (play scenes 1)
"Lucy loves Clojure"
my-stuff.core> (play scenes 2)
"Rich tries a new conditioner"
此play-all
功能无效:
(defn play-all [scenes]
"Play all the scenes"
(let [x (count scenes)]
(for [n (range x)]
(map play scenes n ))))
如何更正此play-all
功能,即如何将播放功能应用于数据范围?
答案 0 :(得分:2)
您不需要for
和 map
。
仅限for
:
user=> (defn play-all [scenes]
#_=> "Play all the scenes"
#_=> (let [x (count scenes)]
#_=> (for [n (range x)]
#_=> (play scenes n ))))
#'user/play-all
user=> (play-all scenes)
("Frankie say relax" "Lucy loves Clojure" "Rich tries a new conditioner")
且只有map
:
user=> (defn play-all [scenes]
#_=> "Play all the scenes"
#_=> (let [x (count scenes)]
#_=> (map #(play scenes %1) (range x))))
#'user/play-all
user=> (play-all scenes)
("Frankie say relax" "Lucy loves Clojure" "Rich tries a new conditioner")
(我更喜欢后者。)
编辑:如果您喜欢->>
,那就更好了:
user=> (defn play-all [scenes]
#_=> "Play all the scenes"
#_=> (->> scenes
#_=> (count)
#_=> (range)
#_=> (map #(play scenes %))))
#'user/play-all
user=> (play-all scenes)
("Frankie say relax" "Lucy loves Clojure" "Rich tries a new conditioner")
答案 1 :(得分:0)
map
遍历集合(或多个集合)以生成序列。
for
从list comprehension构建序列。
在您的情况下,您可以使用其中一个或。
就分解而言,实际上有一个能够播放一个场景的功能会让人感觉很明显:
(defn play-one [scene]
"Play a scene"
(->>
scene
((juxt :subject :action :object))
(interpose " ")
(apply str)))
然后播放第n个可以使用先例定义:
(defn play-nth [scenes n]
"Play the n(th) scene"
(->
scenes
(#(get % n))
play-one))
你有几种方法可以播放所有场景:
(defn play-all-map1 [scenes]
"Play all the scenes"
(map (partial play-nth scenes) (range (count scenes))))
但是你可以真正简化,因为你不需要range
因为scenes
可以被视为一个序列(假设你对索引不感兴趣):
(defn play-all-map2 [scenes]
"Play all the scenes with map"
(map play-one scenes))
使用for
:
(defn play-all-for [scenes]
"Play all the scenes with for"
(for [scene scenes]
(play-one scene)))
答案 2 :(得分:0)
在我们对它做任何事情之前,你的play
函数应该处理一个场景:
(defn play [scene]
"Play a scene"
(->> scene
((juxt :subject :action :object))
(interpose " ")
(apply str)))
你这样使用它:
(play (scenes 0))
;"Frankie say relax"
......这比以前更容易或更难。但
它还使play-all
更简单:
(defn play-all [ss]
(map play ss))
(play-all scenes)
;("Frankie say relax" "Lucy loves Clojure" "Rich tries a new conditioner")
我很想用((juxt :subject :action :object))
中的vals
替换play
,但我们不能依赖地图条目的顺序。