Mapping and transducers seems appropriate, though I'm still wrapping my head around how to make this work. >From the "class with functions" mindset, I need an ArrayList into which I can: a) add members to the list from time to time b) run eval() on it; a conjunctive list will exit false on first false firing of any member, or default exit true otherwise; a disjunctive list will exit true on first true firing of a member, and default false.
When I read the code here, I am not yet clear (sorry, it's on me, not the code) how to make such a "class-like" object. I am still exploring this avenue, as well as looking at java-interop or something about a proxy. Many thanks. Jack On Fri, Aug 14, 2020 at 1:25 AM Oleksandr Shulgin < oleksandr.shul...@zalando.de> wrote: > On Fri, Aug 14, 2020 at 9:05 AM Oleksandr Shulgin < > oleksandr.shul...@zalando.de> wrote: > >> On Fri, Aug 14, 2020 at 7:51 AM Alexandre Almosni < >> alexandre.almo...@gmail.com> wrote: >> >>> Maybe your objects could be defined by a map containing functions and >>> objects. >>> >>> So exampleAndList = {:fn and, :coll [a b c]} >>> >>> >>> And then eval goes through your objects recursively, using >>> >>> (def eval [o] >>> (apply (:fn o) (map eval (:coll o)))) >>> >>> - with a special case that if o is not a map but say a Boolean you just >>> return itself >>> >> >> A slight problem with that approach is that clojure.core/and is not a >> function, but a macro: the reason being is that it stops evaluating forms >> as soon as it hits a falsey value (similar for "or"). >> A smart implementation of And/OrList would like to short-circuit as well >> I guess, so you'll need to express that somehow. >> >> Of the clojure.core library that property is satisfied by transducers: >> https://clojure.org/reference/transducers#_early_termination >> > > I came up with the following: > > ;; and-transducer with early termination: > (defn xand [rf] > (fn > ([] (rf)) > ([res] (rf res)) > ([res inp] (if inp > (rf res inp) > (reduced inp))))) > > ;; reducing function implementing and: > (defn andr > ([] true) > ([i] i) > ([r i] (and r i))) > > ;; noisy variant of get: > (defn noisy-get > ([k] > (fn [m] > (noisy-get m k))) > ([m k] > (println "noisy-get" m k) > (get m k))) > > ;; all in action: > user> (def xf (comp (map (noisy-get :data)) > xand)) > #'user/xf > user> (transduce xf andr [{:data 1} {:data false} {:no-data 3}]) > noisy-get {:data 1} :data > noisy-get {:data false} :data > false > user> (transduce xf andr [{:data 1} {:data 2} {:no-data 3} {:data 4}]) > noisy-get {:data 1} :data > noisy-get {:data 2} :data > noisy-get {:no-data 3} :data > nil > user> (transduce xf andr [{:data 1} {:data 2} {:data 3} {:data 4}]) > noisy-get {:data 1} :data > noisy-get {:data 2} :data > noisy-get {:data 3} :data > noisy-get {:data 4} :data > 4 > > It does feel a bit redundant to have the reducing function on top of a > transducer that accomplishes mostly the same, but I haven't found a way to > make it shorter. > > Cheers, > -- > Alex > >> On 14 Aug 2020, at 02:24, Jack Park <jackp...@topicquests.org> wrote: >>> >>> >>> The problem: >>> >>> In Java, I have an interface *IInferrable* which is basically boolean >>> eval(); >>> >>> Any Java object which extends IInferrable, no matter what it is, will >>> answer to eval() and return a boolean. >>> The idea lies at the heart of an inference engine. >>> >>> But, I also define a class *AndList* which implements IInferrable and >>> extends java.util.ArrayList<Inferrable> >>> >>> So, AndList, and its sibling OrList behave just like a List object, but >>> also will answer to eval() by running the collection and dealing with what >>> each element returns when it, too, is eval()'d. >>> >>> I'd really love to discover how to pull that off in Clojure. >>> >>> > > -- > 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. > To view this discussion on the web visit > https://groups.google.com/d/msgid/clojure/CACACo5TDpMg_CEhE2ytwZv9R1L3%3DifayFLYTs6KC80vON59hiw%40mail.gmail.com > <https://groups.google.com/d/msgid/clojure/CACACo5TDpMg_CEhE2ytwZv9R1L3%3DifayFLYTs6KC80vON59hiw%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/clojure/CAH6s0fyqVFdbv0K3%2B5RA1xw0EU9VHVOJ_b%3DC34EG5igXqVWqhQ%40mail.gmail.com.