在Clojure中重载关键字

Zub*_*air 6 clojure

我有这样的地图:

(def a {:a 1, :b 2})
Run Code Online (Sandbox Code Playgroud)

:我希望重载映射,以便某些关键字执行函数,以便:

(c: a)
Run Code Online (Sandbox Code Playgroud)

可以执行一个功能.这可能吗?

更新:

我意识到我可以这样做:

(def a {:a (fn[] 1) :b (fn[] 2) :c (fn[] x)})
Run Code Online (Sandbox Code Playgroud)

:和:

((c: a))
Run Code Online (Sandbox Code Playgroud)

:但是我必须将我拥有的每个现有地图条目转换为一个函数.

我希望每次都能重新评估这个功能.例如,当我这样做时:

(def ab{:a 1         :b 2         :c ( #(.nextInt (java.util.Random.) 1000))}) 

(str (:c ab) " " (:c ab) " " (:c ab))
Run Code Online (Sandbox Code Playgroud)

我明白了:

61 61 61
Run Code Online (Sandbox Code Playgroud)

而不是三个不同的数字

更新2

我想到了我给出的答案并意识到他是对的,我应该只使用不可变结构.我想出的最终解决方案是拥有一个"丰富"功能,可以根据需要创建动态属性.

 (def a {:a 1, :b 2})
Run Code Online (Sandbox Code Playgroud)

:我希望重载映射,以便某些关键字执行函数,以便:

(str (:c (enrich ab)) " " (:c (enrich ab)) " " (:c (enrich ab)))
Run Code Online (Sandbox Code Playgroud)

每次会产生不同的数字:

58 639 710
Run Code Online (Sandbox Code Playgroud)

mik*_*era 4

我相信,如果您将数据结构设置为记录而不是常规映射,则可以覆盖关联查找的行为。

您基本上需要覆盖 clojure.lang.ILookup :有关更多详细信息,请参阅此问题

这是一个简单的例子:

(deftype TestLookup []
  clojure.lang.ILookup
    (valAt [this k not-found]
      (str "Generated value for key - " k))

    (valAt [this k]
      (.valAt this k nil)))

(def lookupable-object (TestLookup.))

(:somekey lookupable-object)
=> "Generated value for key - :somekey"
Run Code Online (Sandbox Code Playgroud)