News for hackers. Stuff that matters.
Re:Using the Specification Pattern to Build a Data-Driven Ru... by TeMPOraL on Tuesday March 24, 2020 @02:09PM (#22677080)
That's not true. You don't need expression trees (or equivalent), you can walk and interpret the specification directly. Expression trees are just a trick to compile this as code. But you can do that in any language that can compile code at runtime (of which there are, unfortunately, few).

From Common Lisp's perspective, the example given is just:

  `(and (> divident 0.025)
        (< payout-ratio 0.5)
        (or (< pe-ratio 20)
            (< price 130)))
You can walk that tree recursively as-is, calling appropriate operators and substituting correct values.

Or, you can wrap it in a (lambda (divident payout-ratio pe-ratio price) ...) and pass to (compile ...), and get a piece of executable code. With perhaps a line or two of book-keeping (that can be added by your code, and not necessarily typed in by the user), you can make the rule declare which variables it cares about. So a full example:

  (let* ((rule '(lambda (data)
                  (destructuring-bind (&key divident payout-ratio pe-ratio price &allow-other-keys) data
                    (and (> divident 0.025)
                         (< payout-ratio 0.5)
                         (or (< pe-ratio 20)
                             (< price 130))))))
         (executable-rule (compile nil rule)))
    (list (funcall executable-rule '(:divident 0.5 :payout-ratio 0.4 :pe-ratio 50 :price 10 :other-data 42))
          (funcall executable-rule '(:divident 0.5 :payout-ratio 0.5 :pe-ratio 50 :price 10 :other-data 42))))
  
  ;; Result:
  (T NIL)
Re:Using the Specification Pattern to Build a Data-Driven Ru... by NicoJuicy on Tuesday March 24, 2020 @05:19PM (#22679134)
Please read my comment about using the specification-pattern with sql :)

Which, for me, is 90% of the use-cases