I am trying to write a domain-specific production rule language which is compiled down at run-time into Clojure code. It's intended that the rule language should be usable by primary school children with little help.
So far it's going extremely well, except for one problem. If I run it in the REPL, like this, it works: user=> (use 'mw-parser.core :reload) nil user=> (use 'mw-engine.utils) nil user=> (parse-rule "if state is forest and fertility is between 55 and 75 then state should be climax") (fn [cell world] (if (and (= (:state cell) :forest) (or (< 55 (get-int cell :fertility) 75) (> 55 (get-int cell :fertility) 75))) (merge cell {:state :climax}))) user=> (eval *1) #<user$eval1839$fn__1840 user$eval1839$fn__1840@7a52b16b> user=> (apply *1 (list {:state :forest :fertility 60} nil)) {:state :climax, :fertility 60} user=> However, I have a test as follows: ns mw-parser.core-test (:use mw-engine.utils) (:require [clojure.test :refer :all] [mw-parser.core :refer :all])) (deftest rules-tests (testing "if altitude is less than 100 and state is forest then state should be climax and deer should be 3" (is (parse-rule "if altitude is less than 100 and state is forest then state should be climax and deer should be 3")) (is (let [cell (apply (eval (parse-rule "if altitude is less than 100 and state is forest then state should be climax and deer should be 3")) (list {:state :forest :altitude 99} nil))] (and (= (:state cell) :climax) (= (:deer cell) 3)))) )) This fails as follows: simon@engraver:~/workspace/mw-parser$ lein test lein test mw-parser.core-test lein test :only mw-parser.core-test/rules-tests ERROR in (rules-tests) (Compiler.java:6380) if altitude is less than 100 and state is forest then state should be climax and deer should be 3 expected: (let [cell (apply (eval (parse-rule "if altitude is less than 100 and state is forest then state should be climax and deer should be 3")) (list {:state :forest, :altitude 99} nil))] (and (= (:state cell) :climax) (= (:deer cell) 3))) actual: clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to resolve symbol: get-int in this context, compiling:(/tmp/form-init4592216274934008360.clj:1:6384) The function get-int is in mw-engine.utils, and is: (defn get-int "Get the value of a property expected to be an integer from a map; if not present (or not an integer) return 0. * `map` a map; * `key` a symbol or keyword, presumed to be a key into the `map`." [map key] (cond map (let [v (map key)] (cond (and v (integer? v)) v true 0)) true (throw (Exception. "No map passed?")))) I'm trying to understand why this function is not available in the test environment when the anonymous function generated from the rule text is compiled and applied. This matters, because I expect the users of the system to add rules via a web form, so they won't have a REPL. As you can see I've specified that mw-engine.utils is used by the test file, but that does not apparently make the namespace available in eval. It is the eval step, not the apply step, that fails, I've verified that by trying: user=> (use 'mw-parser.core :reload) nil user=> (parse-rule "if state is forest and fertility is between 55 and 75 then state should be climax") (fn [cell world] (if (and (= (:state cell) :forest) (or (< 55 (get-int cell :fertility) 75) (> 55 (get-int cell :fertility) 75))) (merge cell {:state :climax}))) user=> (eval *1) CompilerException java.lang.RuntimeException: Unable to resolve symbol: get-int in this context, compiling:(/tmp/form-init2345285067501587397.clj:1:1) user=> (Note that on this occasion I didn't include the (use 'mw-engine.utils) step) Any assistance gratefully received! -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.