有沒有辦法像(def foo {:two 2 :three (inc (:two this))})
那樣模仿this
變量?更好的是像(def foo {:two 2 :three (inc ::two)})
。有人告訴我有一個圖書館可以做到這一點,但我找不到任何類似的東西。我可以在def中獲得這個變量嗎?
謝謝!
有沒有辦法像(def foo {:two 2 :three (inc (:two this))})
那樣模仿this
變量?更好的是像(def foo {:two 2 :three (inc ::two)})
。有人告訴我有一個圖書館可以做到這一點,但我找不到任何類似的東西。我可以在def中獲得這個變量嗎?
謝謝!
(更新:重排&返工build-map
及(草圖)-m>
宏添加。)
你可以寫這個特殊的例子作爲
(def foo (zipmap [:two :three] (iterate inc 2)))
其發生的最簡單通用的解決方案我在這一刻是
user> (-> {} (assoc :two 2) (#(assoc % :three (inc (:two %)))))
{:three 3, :two 2}
我t實際上非常靈活,但它確實需要您重複寫出assoc
。
爲了實現從問題文本類似的語法,你可以使用這樣的事情:
(defn build-map* [& kvs]
(reduce (fn [m [k v]]
(assoc m k (v m)))
{}
kvs))
(defmacro build-map [& raw-kvs]
(assert (even? (count raw-kvs)))
(let [kvs (map (fn [[k v]] [k `(fn [m#] (let [~'this m#] ~v))])
(partition 2 raw-kvs))]
`(build-map* [email protected])))
user> (build-map :two 2 :three (inc (:two this)))
{:three 3, :two 2}
您可以輕鬆地將其更改爲使用用戶提供的符號,而不是硬編碼this
。或者你可以切換到%
,這只是匿名函數文字之外的常規符號。也許增加一個明確的初始地圖的說法,稱之爲-m>
(在地圖線程),你可以在同樣的結果做
(-m> {} :two 2 :three (inc (:two %)))
。
另一種時髦的方式(主要是爲了好玩):
;;; from Alex Osborne's debug-repl,
;;; see http://gist.github.com/252421
;;; now changed to use &env
(defmacro local-bindings
"Produces a map of the names of local bindings to their values."
[]
(let [symbols (map key &env)]
(zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))
(let [two 2
three (inc two)]
(into {} (map (fn [[k v]] [(keyword k) v]) (local-bindings))))
{:two 2, :three 3}
注意,這也將捕獲任何外令的形式出臺了綁定......
+1針對新複雜魔法構造的現有解決方案。 – Leonel 2010-02-22 16:06:07