rbrush/clara-rules — pull request #43 by mrrodriguez (2014-02-24 03:40:22+00:00)
Title: Rule with `accumulate` without :result-binding fails schema validation

I don't think it is very common that there would be an `accumulate` rule that doesn't use a `:result-binding` , but I have found an issue I believe with how the DSL is parsed in this scenario.

I can demonstrate it with either `mk-rule` (which appears to be deprecated) or with `defrule`;
since they both have the same underlying `clara.rules.dsl/parse-rule*` fn call:

```clj

;;;; Make the rule (2 different ways just to show the same behavior).

(def r (mk-rule [[(accumulate :initial-value []
:reduce-fn (fn [coll i] (conj coll i))
:combine-fn into)
from [SimpleType]]]
(println "done")))

(defrule r2
[(accumulate :initial-value []
:reduce-fn (fn [coll i] (conj coll i))
:combine-fn into)
from [SimpleType]]
=>
(println "done"))

;;;; Display the rule (they both look the same).

(clojure.pprint/pprint r)
;= {:lhs
; [{:result-binding nil, ; HERE lies the issue
; :accumulator
; (clara.rules/accumulate
; :initial-value
; []
; :reduce-fn
; (fn [coll i] (conj coll i))
; :combine-fn
; into),
; :from {:type puzzle.core.SimpleType, :constraints []}}],
; :rhs (println "done")}
; nil

;;;; Fails (both fail the same).

(mk-session [r])
;= ExceptionInfo Value does not match schema: [nil {:result-binding (not (keyword? nil))}] schema.core/validate (core.clj:132)

```

Looking at the clara.rules.schema, the culprit of the validation failure is:

```clj
(def AccumulatorCondition
{:accumulator s/Any
:from FactCondition
(s/optional-key :result-binding) s/Keyword}) ; :result-binding is optional, but fails if it is present and nil
```

There are 2 options that come to mind:
1) Do not return a nil `:result-binding` on a parsed `accumulate` constraint, so the schema is accurate.
2) Change the schema to be flexible to have this optional key, as well as the value at the key being a Keyword or nil.

I think option (1) makes the most sense to me.

That is what I am proposing with this patch.