簡體   English   中英

有沒有辦法可以重用 EDN 中定義的鍵的值?

[英]Is there a way we can re-use value of defined keys in EDN?

有沒有辦法可以重用 EDN 中定義的鍵值?

例如:如果我有以下 EDN

{
   :abc "value1"
   :def :abc
}

當我在 Clojure 中閱讀上面的 EDN 時,我想要傳遞 'def' 鍵,value1 是 :abc 的值。 但是目前:當我使用 EDN 讀取字符串函數讀取它時,會傳遞 :abc 字符串

普通的 EDN 中沒有這樣的東西。 但是您可以構建一個兩階段傳遞,或者通過首先替換 EDN 字符串本身的內容,或者可能更好地在通過操作數據結構解析 EDN 之后執行此操作,例如:

(require '[clojure.edn :as edn])
(require '[clojure.walk :as walk])

(defrecord self [key])
(defn tag-self
  [v]
  (->self v))

(defn custom-readers []
  {'x/self tag-self})

(defn replace-self
  [coll]
  (walk/prewalk
   (fn [form]
     (if (map? form)
       (reduce-kv
        (fn [acc k v]
          (assoc acc k (if (= self (type v))
                         (get form (:key v))
                         v)))
        {}
        form)
       form))
   coll))

(replace-self
 (edn/read-string
  {:readers (custom-readers)}
  "[{:abc \"value1\"
     :def #x/self :abc}
    {:abc {:bbb \"value2\"
           :def #x/self :bbb}
     :def #x/self :abc
     :xyz {:aaa \"value3\"
           :nope #x/self :abc
           :def #x/self :aaa}}]"))

將返回:

[{:abc "value1", :def "value1"}
 {:abc {:bbb "value2", :def "value2"},
  :def {:bbb "value2", :def "value2"},
  :xyz {:aaa "value3", :nope nil, :def "value3"}}]

訣竅是我使用我創建的#x/self標簽讀取器標記對當前映射的另一個鍵的引用,它將值包裝在一個self記錄中。 現在我們只是遍歷返回的數據結構,每次遇到self類型時,我們將其替換為同一映射中其:key屬性的值。

上述replace-self沃克是遞歸的,所以你可以看到,它可以處理嵌套的地圖,它甚至可以取代self的內部地圖本身是引用self引用。 它只進行局部作用域,所以:nope #x/self :abc沒有被父映射中的:abc的值替換,並且由於它自己的映射中沒有:abc鍵,它的值被設置為nil

自定義標簽是可選的,我這樣做是因為現在它適用於任何類型的鍵。 但是你可以使用keyword? 如果您希望這成為他們的行為,那么也可以在 replace-self 中:

(defn replace-self
  [coll]
  (walk/prewalk
   (fn [form]
     (if (map? form)
       (reduce-kv
        (fn [acc k v]
          (assoc acc k (if (keyword? v)
                         (v form)
                         v)))
        {}
        form)
       form))
   coll))

(replace-self
 (edn/read-string
  "[{:abc \"value1\"
     :def :abc}
    {:abc {:bbb \"value2\"
           :def :bbb}
     :def :abc
     :xyz {:aaa \"value3\"
           :nope :abc
           :def :aaa}}]"))

這將返回與之前相同的結果,只是不需要自定義標簽和自我記錄:

[{:abc "value1", :def "value1"}
 {:abc {:bbb "value2", :def "value2"},
  :def {:bbb "value2", :def "value2"},
  :xyz {:aaa "value3", :nope nil, :def "value3"}}]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM