Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以从同一映射中的另一个值引用clojure hashmap值吗?_Clojure - Fatal编程技术网

我可以从同一映射中的另一个值引用clojure hashmap值吗?

我可以从同一映射中的另一个值引用clojure hashmap值吗?,clojure,Clojure,我试图想出一些方法,让clojure hashmap中的值相互引用。从概念上讲,类似这样的情况: (def m {:a 1 :b 5 :c (+ (:a m) (:b m))} ;Implies (= (:c m) 6) 当然,这不起作用,因为我循环引用m。我可以做类似的事情 (def m {:a 1 :b 5 :c (fn [a b] (+ a b))}) ((:c m) (:a m) (:b m)) ;=> 6 但这并没有带来任何好处,因为我仍然需要知道将哪个a和b放入函数中。另

我试图想出一些方法,让clojure hashmap中的值相互引用。从概念上讲,类似这样的情况:

(def m {:a 1 :b 5 :c (+ (:a m) (:b m))}  ;Implies (= (:c m) 6)
当然,这不起作用,因为我循环引用
m
。我可以做类似的事情

(def m {:a 1 :b 5 :c (fn [a b] (+ a b))})
((:c m) (:a m) (:b m)) ;=> 6
但这并没有带来任何好处,因为我仍然需要知道将哪个
a
b
放入函数中。另一次尝试:

(def m {:a 1 :b 5 :c (fn [m] (+ (:a m) (:b m)))})
((:c m) m) ;=> 6
这更好了一点,因为我现在已经将函数内部化为一个映射,虽然不是专门针对这个映射。我可以试着用这样的东西来解决这个问题

(defn new-get [k m]
  (let [v-or-fn (get m k)]
    (if (fn? v-or-fn) (v-or-fn m) v-or-fn)))

(def m {:a 1 :b 5 :c (fn [m] (+ (:a m) (:b m)))})
(new-get :a m) ;=> 1
(new-get :b m) ;=> 5
(new-get :c m) ;=> 6

我想这是我能做的最好的了。我错过了更聪明的东西吗?

因为
c
是一个派生值,所以是
a
b
的函数,您最好定义一个生成此映射的函数:

 (defn my-map-fn [a b]
   {:a a :b b :c (+ a b)})

 (def my-map (my-map-fn 1 2))
 (:c my-map) ;;=> 3

正如我在上面的评论中所说,您可以使用let表单:

(def m 
  (let [a 1 b 5] 
    {:a a :b b :c (+ a b)}))
(for [x (...) xs]
     :let [y (+ x 1)]
     ; ...
如果您使用的是仅在m定义中已知的值,那么这应该是很好的。否则,最好使用函数参数作为参数

顺便说一句,您可以自由使用def中通常在clojure中使用的所有内容。此外,有时您可以在其他一些表单中自由使用let-in糖化表单(尽管这种let使用的机制与通常的let-form不同):


无法控制自己编写宏:

(defmacro defmap [name m]
  (let [mm (into [] (map (fn [[k v]] `[~k (fn [~name] ~v)]) m))]
    `(def ~name
       (loop [result# {} mp# (seq ~mm)]
         (if (seq mp#)
           (let [[k# v#] (first mp#)]
             (recur (assoc result# k# (v# result#)) (rest mp#)))
           result#)))))

(defmap m [[:a 1]
           [:b 5]
           [:c (+ (:a m) (:b m))]])

;; m is {:a 1 :b 5 :c 6}
以下是我对它的看法:

(defmacro let映射[&bindings]
(让[符号键(->>绑定(分区2)(映射优先))]
`(让[~@bindings]
(插入{}~(mapv(fn[k][(关键字k)k])符号键()())))
;; 如果您将其视为类似于let,则当其更复杂时:
(让我们看看地图
a 1
b 5
c(+ab));=>{:a1,:b5,:c6}
;; 如果您将其视为一个扩展的哈希映射,当它足够简单时:
(让我们映射A1,B5,c(+AB));=>{:a1,:b5,:c6}

(defm(让[a1b5]{:aA:bB:c(+ab)})有什么问题?
?我想我不知道你能做
def
里面。美好的我现在已经尝试了这两种方法。我遇到的一个困难是处理可传递依赖项。说键
:d
取决于
:c
:b
的结果。我最后不得不调用map生成器函数,输入两次
:b
。(定义我的map fn[ab](让[c(+ab),d(+bc)]{:aa:bb:cc:dd})