2013-04-09 85 views
1

我有一張表示關於subversion commit的信息。idomatic clojure前綴替換

實施例的內容:

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

但這意味着我必須在我的修復庫中爲每個新替換項添加一個額外的包裝器。

我想簡單地說:

  • 鑑於提交地圖
  • 提取:倉庫值
  • 遍歷更換名單前綴
  • 如果任何前綴匹配,替換:倉庫價值使用新字符串
  • 否則,請保留:存儲庫值。

我似乎無法構建正確的循環,減少或其他解決方案。

回答

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

+0

完美。謝謝 :-) – toolkit 2013-04-09 10:39:13

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)