如何将函数应用于 Clojure 中的范围?
How to apply a function to a range in Clojure?
我是 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
函数,即如何将播放函数应用于数据范围?
您不需要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")
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)))
在我们对其进行任何操作之前,您的 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")
我很想在 play
中用 vals
替换 ((juxt :subject :action :object))
,但我们不能依赖映射条目的顺序。
我是 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
函数,即如何将播放函数应用于数据范围?
您不需要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")
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)))
在我们对其进行任何操作之前,您的 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")
我很想在 play
中用 vals
替换 ((juxt :subject :action :object))
,但我们不能依赖映射条目的顺序。