Clojure评估范围问题

时间:2017-10-22 21:58:30

标签: clojure macros eval

我正在尝试执行以下操作: 1.我有多个代理是包含表达式的地图。 (见前三行代码)

  1. 我想要的是,在let范围内的给定日期,上面的表达式应该绑定到本地日期。 (其余部分)

  2. 我做错了什么,我应该如何处理这个问题?感谢。

  3. ---以下所有代码

    (def dates [20171002 20171003])
    (def date 20171002)
    (def data (zipmap dates (repeatedly (count dates) #(ref {:entry true :exit true} )) ))
    
    
    (dosync (alter (data 20171003) assoc-in [:entry] false))
    
    (println data)
    (def agent-1 {:entry-condition '((data date) :entry)})
    
    ;(eval (:entry-condition agent-1))
    ;(data date)
    
    (def date-given 20171003)
    
    (let [date date-given
          enter? (eval (:entry-condition agent-1))]
      (if enter? (println "hi") (println "correct")))
    
    ;; i need correct, not hi.
    

1 个答案:

答案 0 :(得分:1)

首先,+1给@amalloy评论此eval不是你在这里的朋友(some say evil)。

问题的根本原因是 eval在当前命名空间中查找而不是当前词法范围。这在this answer进一步解释。

因此,要重新绑定date,您需要使用binding而不是let(至少对于日期符号)。然后它也需要是动态的。在你的日期定义中,你可以通过以下方式使其变得动态:

(def ^:dynamic date 20171002)
;; or better yet:
(declare ^:dynamic date)

然后当你使用它时,

(binding [date date-given]
  (let [enter? (eval (:entry-condition agent-1))]
    (if enter?
      (println "NO")
      (println "correct") )) )