【问题标题】:idiomatic clojure prefix replacement惯用的 clojure 前缀替换
【发布时间】:2019-03-08 05:29:42
【问题描述】:

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

示例内容:

(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 值。

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

【问题讨论】:

    标签: clojure


    【解决方案1】:

    你可以使用函数组合:

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

    【讨论】:

      【解决方案2】:

      这样的事情怎么样?

      (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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-25
        • 2021-11-14
        • 1970-01-01
        • 1970-01-01
        • 2011-03-15
        • 1970-01-01
        相关资源
        最近更新 更多