Clojure中的重载关键字
我有一张这样的地图:Clojure中的重载关键字,clojure,Clojure,我有一张这样的地图: (def a {:a 1, :b 2}) :我希望重载映射,以便某些关键字执行函数,以便: (c: a) (str (:c (enrich ab)) " " (:c (enrich ab)) " " (:c (enrich ab))) 可以执行一个函数。这可能吗 更新: 我确实意识到我可以做以下事情: (def a {:a (fn[] 1) :b (fn[] 2) :c (fn[] x)}) :及: :但我必须将现有的每个地图条目转换为函数 我希望每次都“重新评估”
(def a {:a 1, :b 2})
:我希望重载映射,以便某些关键字执行函数,以便:
(c: a)
(str (:c (enrich ab)) " " (:c (enrich ab)) " " (:c (enrich ab)))
可以执行一个函数。这可能吗
更新:
我确实意识到我可以做以下事情:
(def a {:a (fn[] 1) :b (fn[] 2) :c (fn[] x)})
:及:
:但我必须将现有的每个地图条目转换为函数
我希望每次都“重新评估”函数。例如,当我这样做时:
(def ab{:a 1 :b 2 :c ( #(.nextInt (java.util.Random.) 1000))})
(str (:c ab) " " (:c ab) " " (:c ab))
我得到:
61 61 61
而不是三个不同的数字
更新2
我考虑了我得到的答案,意识到他是对的,我应该只使用不变的结构。我提出的最后一个解决方案是拥有一个“丰富”功能,可以根据需要创建动态属性
(def a {:a 1, :b 2})
:我希望重载映射,以便某些关键字执行函数,以便:
(c: a)
(str (:c (enrich ab)) " " (:c (enrich ab)) " " (:c (enrich ab)))
每次将生成不同的数字,如下所示:
58 639 710
在我看来,使用同一个映射有时传回不可变值,有时传回不纯函数似乎违背了不可变映射应该用于的精神。与其这样做,我建议使用一个引用类型,它指向一个只有数据值的不可变映射。然后,当其中一个数据值需要不同时,将引用类型指向反映任何更改的新不可变映射。我相信,如果将数据结构设置为记录而不是常规映射,则可以覆盖关联查找的行为 您基本上需要覆盖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"
Clojure更喜欢纯数据结构,而不是结合数据和行为的对象。通过函数访问数据结构,可以获得所需的行为:
(def base-foo {:a 1, :b 2})
(defn foo [key]
(if (= :c key)
(rand-int 100)
(get base-foo key)))
(str (foo :c) " " (foo :c) " " (foo :c))
;;=> "66 52 25"
我希望在访问字段时对函数求值,因为返回的值是计算出来的,并且可以更改。我知道这并不是像我的简单示例所示的那样是不变的,但我只是展示了一个简单的案例哦,好吧,所以你要计算的函数不是纯函数。是的,对不起,我没有提到,在我最初的问题中,我尝试过这个,但它不允许我将项目关联到其中。我选择了你的答案,尽管我可能无法使用它,因为我对你试图这么做印象深刻:)