我有一张代表有关subversion提交信息的地图。
示例内容:
(def commit
{:repository "/var/group1/project1"
:revision-number "1234"
:author "toolkit"
etc..}
我想根据前缀匹配更改存储库,以便:
/var/group1 maps to http://foo/group1
/var/group2 maps to http://bar/group2
我创建了两个函数,如:
(defn replace-fn [prefix replacement]
(fn [str]
(if (.startsWith str prefix)
(.replaceFirst str prefix replacement)
str)))
(def replace-group1 (replace-fn "/var/group1" "http://foo/group1"))
(def replace-group2 (replace-fn "/var/group2" "http://bar/group2"))
现在我必须应用它们:
(defn fix-repository [{:keys [repository] :as commit}]
(assoc commit :repository
(replace-group1
(replace-group2 repository))))
但这意味着我必须在我的fix-repository中为每个新的替代品添加一个额外的包装器。
我想简单地说:
我似乎无法构建正确的循环,减少或其他解决方案。
答案 0 :(得分:2)
您可以使用功能组合:
(def commit
{:repository "/var/group2/project1"
:revision-number "1234"
:author "toolkit"})
(defn replace-fn [prefix replacement]
(fn [str]
(if (.startsWith str prefix)
(.replaceFirst str prefix replacement)
str)))
(def replacements
(comp (replace-fn "/var/group1" "http://foo/group1")
(replace-fn "/var/group2" "http://foo/group2")))
(defn fix-repository [commit replacements]
(update-in commit [:repository] replacements))
(fix-repository commit replacements)
答案 1 :(得分:1)
这样的事情怎么样?
(defn replace-any-prefix [replacements-list string]
(or (first
(filter identity
(map (fn [[p r]]
(when (.startsWith string p)
(.replaceFirst string p r)))
replacements-list)))
string)))
(update-in commit
[:repository]
(partial replace-any-prefix
[["/var/group1" "http://foo/group1"]
["/var/group2" "http:/foo/group2"]]))
更新文档:http://clojuredocs.org/clojure_core/clojure.core/update-in