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.

Reply via email to