rbrush/clara-rules — pull request #33 by mrrodriguez (2013-12-23 17:30:20+00:00)
Title: AOT compilation of clara with dynamically defined types and rules

If a consumer of clara-rules chooses to AOT compile their project and transitively AOT compile clara-rules, the `clojure.lang.RT/baseLoader` will be referencing the context `ClassLoader` instead of a `DynamicClassLoader`, given the Clojure defaults. The context `ClassLoader` is typically the system loader. The consequence of this is that the consumer were to dynamically create new classes and dynamically make clara rules referencing those dynamic types, the reflection of these record fields would fail.

To guarantee that the `clara.rules.compiler/reflector` has a `clojure.lang.DynamicClassLoader` reference for reflection, an instance needs to be given to it. The most appropriate way to create this `DynamicClassLoader` would be to create a new one by calling `clojure.lang.RT#makeClassLoader`, which will give the base loader as the parent of the dynamic loader (with USE_CONTEXT_CLASSLOADER = true dynamically set).

I would like to point out, Clojure has a static function defined for `clojure.lang.IRecord` types, that gives meta info on the "basis" fields of the record. This can be called like:

```clj
(defrecord MyType [x])

(MyType/getBasis)
;= returns vector of Symbols, here would be -> [x]

```

This is mentioned
@ [http://dev.clojure.org/display/design/defrecord+improvements] and
@ [https://groups.google.com/forum/#!topic/clojure/1jDRPI0Bbs8]

The claim is that this static function is meant to "for tool support" and not "for Clojure code". I'm not sure I see the difference in many scenarios.
So it may be best to stick to the reflection approach currently in use, but this could be simpler.

I think to use it in clara compiler though, an `eval` call would be needed, due to not being able to call a static method on a type not known at compile-time (see [http://stackoverflow.com/questions/9167457/in-clojure-how-to-use-a-java-class-dynamically]).

Anyways, the alternative I can think of would look like this:

```clj

(defn get-fields
"Returns a map of field name to a symbol representing the function used to access it."
[type]
(cond
(and (compiling-cljs?) (symbol? type)) (get-cljs-accessors type)
(isa? type clojure.lang.IRecord) (into {} ; Changed here
(map #(vector % (symbol (str ".-" (name %))))
(eval `(. ~type ~'getBasis))))
(class? type) (get-bean-accessors type) ; Treat unrecognized classes as beans.
:default [])) ; Other types have no accessors.

```

Unfortunately, it does not seem that a similar function has been offered in cljs as of yet.