1

我有一张地图,表示有关颠覆提交的信息。

示例内容:

(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

我创建了 2 个函数,例如:

(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))))

但这意味着我必须在我的修复存储库中为每个新的替换添加一个额外的包装器。

我想简单地说:

  • 给定一个提交映射
  • 提取 :repository 值
  • 循环遍历替换前缀列表
  • 如果任何前缀匹配,则将 :repository 值替换为新字符串
  • 否则,请单独保留 :repository 值。

我似乎无法为此建立正确的循环、减少或其他解决方案。

4

2 回答 2

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)
于 2013-04-09T10:35:29.520 回答
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

于 2013-04-09T10:35:39.123 回答