【问题标题】:Clojure eval scope issuesClojure 评估范围问题
【发布时间】:2018-04-03 10:08:12
【问题描述】:

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

  1. 我想要的是,在 let 范围内的给定日期,上述表达式形式的地图应绑定到本地日期。 (其余行)

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

--- 下面的所有代码

(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.

【问题讨论】:

  • 不要存储表达式和eval它们:存储函数并传递参数。
  • 感谢 amalloy 和 Phil Cooper。你的两个想法都很有用,我使用函数和传递参数来满足我的需要。

标签: clojure macros eval


【解决方案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") )) )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    相关资源
    最近更新 更多