1

I am trying to do the following: 1. I have multiple agents who are maps that contain expressions. (see first three lines of code)

  1. What I want is, on a given date inside a let scope, the above expression form the map should bind to the local date. (rest of the lines)

  2. What am i doing wrong, how should I approach this problem? Thanks.

--- all code below

(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.
Phil Cooper
  • 5,747
  • 1
  • 25
  • 41

1 Answers1

1

First things first, +1 to @amalloy comment that this eval is not you friend here (some say evil).

The root cause of the problem here is that eval looks in the current namespace and not the current lexical scope. That is further explained in this answer.

So, to rebind date, you need to use binding rather than let (at least for the date symbol). It then also needs to be dynamic. In your def of date, you can make it dynamic with:

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

then when you use it,

(binding [date date-given]
  (let [enter? (eval (:entry-condition agent-1))]
    (if enter?
      (println "NO")
      (println "correct") )) )
Phil Cooper
  • 5,747
  • 1
  • 25
  • 41