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.

Reply via email to