Re: First post: how to mimic a Java List with types?

2020-08-15 Thread Erik Assum
Why not tease things apart?

(defn eval [x] ...)

(some eval my-list) ;; or list
(every? eval my-list) ;; and list

https://clojuredocs.org/clojure.core/some
https://clojuredocs.org/clojure.core/every_q

Now, you can make the eval function polymorphic in several ways, simplest is to 
case or cond on some property of x. You could also use multimethods or a 
protocol to achieve this. 

https://insideclojure.org/2015/04/27/poly-perf/

Erik. 
-- 
i farta

> 15. aug. 2020 kl. 02:04 skrev matthew...@gmail.com 
> :
> 
> 
> Another option would be to do what Alex is suggesting and define and as a 
> function. Just because it’s a macro in clojure.core doesn’t mean you can’t 
> write your own :)
> 
> (defn eval' [x]
>   (if (map? x)
> (apply (:fn x) (:coll x))
> x))
> 
> (defn and-list [& items]
>   (let [if? (fn [x] (if x true false))
> and' (fn [& args] (every? if? args))]
> {:fn and' :coll items}))
> 
> (eval' true) ;=> true
> (eval' false) ;=> false
> (eval' (and-list 1 2 3)) ;=> true
> (eval' (and-list 1 2 3 false)) ;=> false
> Ditto with or.
> 
>> On Friday, August 14, 2020 at 4:27:19 PM UTC-5 jack...@topicquests.org wrote:
>> Alex,
>> 
>> I plan to explore this idea.
>> Many thanks!
>> 
>> Jack
>> 
>>> On Fri, Aug 14, 2020 at 1:38 PM Oleksandr Shulgin  
>>> wrote:
>>> 
>>> 
>> 
>>> 
>>> Nevermind transducers: I've just realized that reduced can be used with the 
>>> normal reduce.  E.g. here's short-circuiting AND-reduction fn:
>>> 
>>> (defn andr
>>>   ([] true)
>>>   ([i] i)
>>>   ([r i] (let [o (and r i)]
>>>(if o
>>>  o
>>>  (reduced o)
>>> 
>>> When it comes to the actual lists, it depends how you'd like to represent 
>>> them.  E.g. I could imagine something like the following can be a useful 
>>> notation:
>>> 
>>> [:and 1 2 [:or 3 4] 5]
>>> 
>>> or even more direct:
>>> 
>>> (quote (and 1 2 (or 3 4) 5))
>>> 
>>> If you really want an interface-like look and feel, then protocols might be 
>>> the right answer:
>>> 
>>> (defprotocol Evaluable
>>>   (evaluate [this]))
>>> 
>>> (defrecord AndList [items]
>>>   Evaluable
>>>   (evaluate [this]
>>> (reduce andr (:items this
>>> 
>>> user> (evaluate (->AndList [1 2 3]))
>>> 3
>>> user> (evaluate (->AndList [1 false 3]))
>>> false
>>> 
>>> To complete it, you'll need to add the OrList and sneak (map evaluate) in 
>>> the reduce call in both And- and OrList.
>>> 
>>> Cheers,
>>> --
>>> Alex
>> 
>>> 
> 
> -- 
> 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/cfac729f-b8e4-4f95-94b0-78345d10f457n%40googlegroups.com.

-- 
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/5B42B3BC-E20D-446E-82EF-0D1BFC36DA5F%40assum.net.


Re: First post: how to mimic a Java List with types?

2020-08-15 Thread Jack Park
Hi Erik,

I think that teasing things apart helps along some dimensions, but the
problem I face, still thinking like a Java hacker, is that I need to put
things together:

I need to construct a *type*  (deftype) which honors two different
interfaces, a list, and an evaluable object. I need the type because I want
to create it, then add members to the list, and then one of:
a) insert the object into another one (building and/or trees)
b) evaluate it - when it is the root of the tree.

Members in such lists can be either other evaluable lists, or they can be
evaluable objects which perform computations - even with side effects - but
which return a boolean.

The several ideas posted in this thread are greatly helping me to see
through this situation with fresh eyes, but, thus far, nothing has
convinced me to drop the goal of creating a type which is a list and
evaluable, into which I can insert conjunction or disjunction evaluators.

Many thanks,
Jack

On Sat, Aug 15, 2020 at 12:14 AM Erik Assum  wrote:

> Why not tease things apart?
>
> (defn eval [x] ...)
>
> (some eval my-list) ;; or list
> (every? eval my-list) ;; and list
>
> https://clojuredocs.org/clojure.core/some
> https://clojuredocs.org/clojure.core/every_q
>
> Now, you can make the eval function polymorphic in several ways, simplest
> is to case or cond on some property of x. You could also use multimethods
> or a protocol to achieve this.
>
> https://insideclojure.org/2015/04/27/poly-perf/
>
> Erik.
> --
> i farta
>
> 15. aug. 2020 kl. 02:04 skrev matthew...@gmail.com <
> matthewdowne...@gmail.com>:
>
> 
>
> Another option would be to do what Alex is suggesting and define and as a
> function. Just because it’s a macro in clojure.core doesn’t mean you can’t
> write your own :)
>
> (defn eval' [x]
>   (if (map? x)
> (apply (:fn x) (:coll x))
> x))
>
> (defn and-list [& items]
>   (let [if? (fn [x] (if x true false))
> and' (fn [& args] (every? if? args))]
> {:fn and' :coll items}))
>
> (eval' true) ;=> true
> (eval' false) ;=> false
> (eval' (and-list 1 2 3)) ;=> true
> (eval' (and-list 1 2 3 false)) ;=> false
>
> Ditto with or.
> ​
> On Friday, August 14, 2020 at 4:27:19 PM UTC-5 jack...@topicquests.org
> wrote:
>
>> Alex,
>>
>> I plan to explore this idea.
>> Many thanks!
>>
>> Jack
>>
>> On Fri, Aug 14, 2020 at 1:38 PM Oleksandr Shulgin 
>> wrote:
>>
>>> 
>>>
>>>
>>> Nevermind transducers: I've just realized that reduced can be used with
>>> the normal reduce.  E.g. here's short-circuiting AND-reduction fn:
>>>
>>> (defn andr
>>>   ([] true)
>>>   ([i] i)
>>>   ([r i] (let [o (and r i)]
>>>(if o
>>>  o
>>>  (reduced o)
>>>
>>> When it comes to the actual lists, it depends how you'd like to
>>> represent them.  E.g. I could imagine something like the following can be a
>>> useful notation:
>>>
>>> [:and 1 2 [:or 3 4] 5]
>>>
>>> or even more direct:
>>>
>>> (quote (and 1 2 (or 3 4) 5))
>>>
>>> If you really want an interface-like look and feel, then protocols might
>>> be the right answer:
>>>
>>> (defprotocol Evaluable
>>>   (evaluate [this]))
>>>
>>> (defrecord AndList [items]
>>>   Evaluable
>>>   (evaluate [this]
>>> (reduce andr (:items this
>>>
>>> user> (evaluate (->AndList [1 2 3]))
>>> 3
>>> user> (evaluate (->AndList [1 false 3]))
>>> false
>>>
>>> To complete it, you'll need to add the OrList and sneak (map evaluate)
>>> in the reduce call in both And- and OrList.
>>>
>>> Cheers,
>>> --
>>> Alex
>>>
>> 
>>>
>> --
> 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/cfac729f-b8e4-4f95-94b0-78345d10f457n%40googlegroups.com
> 
> .
>
> --
> 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 unsubsc

Re: First post: how to mimic a Java List with types?

2020-08-15 Thread Brandon R
Hey Jack,

Just been a fly on the wall for this convo, and aside from offering a
specific solution, which others have done, I'm pretty certain this can be
done with just protocols and records. Make a record (like your type) that
implements the two protocols (like your interfaces). You could achieve your
desired functionality without records and protocols but what you describe
sounds like a fitting case for them.

Members in such lists can be either other evaluable lists, or they can be
> evaluable objects which perform computations
>

A simple Clojure list/vector can hold any type of data you put into it. So
your record can hold a vector of these things, which can be represented as
Clojure data structure (lists / maps / etc).

You say you *need* to construct a type, but I urge you to challenge this
assumption, again and again if needed. I think it's natural to think you
need a type because of coming from Java/OOP land, especially if you were
there a long time. Old patterns die hard?

I could be wrong though. :)


My 2 cents,
Brandon

On Sat, Aug 15, 2020 at 12:42 PM Jack Park  wrote:

> Hi Erik,
>
> I think that teasing things apart helps along some dimensions, but the
> problem I face, still thinking like a Java hacker, is that I need to put
> things together:
>
> I need to construct a *type*  (deftype) which honors two different
> interfaces, a list, and an evaluable object. I need the type because I want
> to create it, then add members to the list, and then one of:
> a) insert the object into another one (building and/or trees)
> b) evaluate it - when it is the root of the tree.
>
> Members in such lists can be either other evaluable lists, or they can be
> evaluable objects which perform computations - even with side effects - but
> which return a boolean.
>
> The several ideas posted in this thread are greatly helping me to see
> through this situation with fresh eyes, but, thus far, nothing has
> convinced me to drop the goal of creating a type which is a list and
> evaluable, into which I can insert conjunction or disjunction evaluators.
>
> Many thanks,
> Jack
>
> On Sat, Aug 15, 2020 at 12:14 AM Erik Assum  wrote:
>
>> Why not tease things apart?
>>
>> (defn eval [x] ...)
>>
>> (some eval my-list) ;; or list
>> (every? eval my-list) ;; and list
>>
>> https://clojuredocs.org/clojure.core/some
>> https://clojuredocs.org/clojure.core/every_q
>>
>> Now, you can make the eval function polymorphic in several ways, simplest
>> is to case or cond on some property of x. You could also use multimethods
>> or a protocol to achieve this.
>>
>> https://insideclojure.org/2015/04/27/poly-perf/
>>
>> Erik.
>> --
>> i farta
>>
>> 15. aug. 2020 kl. 02:04 skrev matthew...@gmail.com <
>> matthewdowne...@gmail.com>:
>>
>> 
>>
>> Another option would be to do what Alex is suggesting and define and as
>> a function. Just because it’s a macro in clojure.core doesn’t mean you
>> can’t write your own :)
>>
>> (defn eval' [x]
>>   (if (map? x)
>> (apply (:fn x) (:coll x))
>> x))
>>
>> (defn and-list [& items]
>>   (let [if? (fn [x] (if x true false))
>> and' (fn [& args] (every? if? args))]
>> {:fn and' :coll items}))
>>
>> (eval' true) ;=> true
>> (eval' false) ;=> false
>> (eval' (and-list 1 2 3)) ;=> true
>> (eval' (and-list 1 2 3 false)) ;=> false
>>
>> Ditto with or.
>> ​
>> On Friday, August 14, 2020 at 4:27:19 PM UTC-5 jack...@topicquests.org
>> wrote:
>>
>>> Alex,
>>>
>>> I plan to explore this idea.
>>> Many thanks!
>>>
>>> Jack
>>>
>>> On Fri, Aug 14, 2020 at 1:38 PM Oleksandr Shulgin <
>>> oleksand...@zalando.de> wrote:
>>>
 


 Nevermind transducers: I've just realized that reduced can be used with
 the normal reduce.  E.g. here's short-circuiting AND-reduction fn:

 (defn andr
   ([] true)
   ([i] i)
   ([r i] (let [o (and r i)]
(if o
  o
  (reduced o)

 When it comes to the actual lists, it depends how you'd like to
 represent them.  E.g. I could imagine something like the following can be a
 useful notation:

 [:and 1 2 [:or 3 4] 5]

 or even more direct:

 (quote (and 1 2 (or 3 4) 5))

 If you really want an interface-like look and feel, then protocols
 might be the right answer:

 (defprotocol Evaluable
   (evaluate [this]))

 (defrecord AndList [items]
   Evaluable
   (evaluate [this]
 (reduce andr (:items this

 user> (evaluate (->AndList [1 2 3]))
 3
 user> (evaluate (->AndList [1 false 3]))
 false

 To complete it, you'll need to add the OrList and sneak (map evaluate)
 in the reduce call in both And- and OrList.

 Cheers,
 --
 Alex

>>> 

>>> --
>> 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 m

Re: First post: how to mimic a Java List with types?

2020-08-15 Thread Jack Park
Brandon!

That just might be the idea I needed. Thank you.

Film at 11...

On Sat, Aug 15, 2020 at 2:28 PM Brandon R  wrote:

> Hey Jack,
>
> Just been a fly on the wall for this convo, and aside from offering a
> specific solution, which others have done, I'm pretty certain this can be
> done with just protocols and records. Make a record (like your type) that
> implements the two protocols (like your interfaces). You could achieve your
> desired functionality without records and protocols but what you describe
> sounds like a fitting case for them.
>
> Members in such lists can be either other evaluable lists, or they can be
>> evaluable objects which perform computations
>>
>
> A simple Clojure list/vector can hold any type of data you put into it. So
> your record can hold a vector of these things, which can be represented as
> Clojure data structure (lists / maps / etc).
>
> You say you *need* to construct a type, but I urge you to challenge this
> assumption, again and again if needed. I think it's natural to think you
> need a type because of coming from Java/OOP land, especially if you were
> there a long time. Old patterns die hard?
>
> I could be wrong though. :)
>
>
> My 2 cents,
> Brandon
>
> On Sat, Aug 15, 2020 at 12:42 PM Jack Park 
> wrote:
>
>> Hi Erik,
>>
>> I think that teasing things apart helps along some dimensions, but the
>> problem I face, still thinking like a Java hacker, is that I need to put
>> things together:
>>
>> I need to construct a *type*  (deftype) which honors two different
>> interfaces, a list, and an evaluable object. I need the type because I want
>> to create it, then add members to the list, and then one of:
>> a) insert the object into another one (building and/or trees)
>> b) evaluate it - when it is the root of the tree.
>>
>> Members in such lists can be either other evaluable lists, or they can be
>> evaluable objects which perform computations - even with side effects - but
>> which return a boolean.
>>
>> The several ideas posted in this thread are greatly helping me to see
>> through this situation with fresh eyes, but, thus far, nothing has
>> convinced me to drop the goal of creating a type which is a list and
>> evaluable, into which I can insert conjunction or disjunction evaluators.
>>
>> Many thanks,
>> Jack
>>
>> On Sat, Aug 15, 2020 at 12:14 AM Erik Assum  wrote:
>>
>>> Why not tease things apart?
>>>
>>> (defn eval [x] ...)
>>>
>>> (some eval my-list) ;; or list
>>> (every? eval my-list) ;; and list
>>>
>>> https://clojuredocs.org/clojure.core/some
>>> https://clojuredocs.org/clojure.core/every_q
>>>
>>> Now, you can make the eval function polymorphic in several ways,
>>> simplest is to case or cond on some property of x. You could also use
>>> multimethods or a protocol to achieve this.
>>>
>>> https://insideclojure.org/2015/04/27/poly-perf/
>>>
>>> Erik.
>>> --
>>> i farta
>>>
>>> 15. aug. 2020 kl. 02:04 skrev matthew...@gmail.com <
>>> matthewdowne...@gmail.com>:
>>>
>>> 
>>>
>>> Another option would be to do what Alex is suggesting and define and as
>>> a function. Just because it’s a macro in clojure.core doesn’t mean you
>>> can’t write your own :)
>>>
>>> (defn eval' [x]
>>>   (if (map? x)
>>> (apply (:fn x) (:coll x))
>>> x))
>>>
>>> (defn and-list [& items]
>>>   (let [if? (fn [x] (if x true false))
>>> and' (fn [& args] (every? if? args))]
>>> {:fn and' :coll items}))
>>>
>>> (eval' true) ;=> true
>>> (eval' false) ;=> false
>>> (eval' (and-list 1 2 3)) ;=> true
>>> (eval' (and-list 1 2 3 false)) ;=> false
>>>
>>> Ditto with or.
>>> ​
>>> On Friday, August 14, 2020 at 4:27:19 PM UTC-5 jack...@topicquests.org
>>> wrote:
>>>
 Alex,

 I plan to explore this idea.
 Many thanks!

 Jack

 On Fri, Aug 14, 2020 at 1:38 PM Oleksandr Shulgin <
 oleksand...@zalando.de> wrote:

> 
>
>
> Nevermind transducers: I've just realized that reduced can be used
> with the normal reduce.  E.g. here's short-circuiting AND-reduction fn:
>
> (defn andr
>   ([] true)
>   ([i] i)
>   ([r i] (let [o (and r i)]
>(if o
>  o
>  (reduced o)
>
> When it comes to the actual lists, it depends how you'd like to
> represent them.  E.g. I could imagine something like the following can be 
> a
> useful notation:
>
> [:and 1 2 [:or 3 4] 5]
>
> or even more direct:
>
> (quote (and 1 2 (or 3 4) 5))
>
> If you really want an interface-like look and feel, then protocols
> might be the right answer:
>
> (defprotocol Evaluable
>   (evaluate [this]))
>
> (defrecord AndList [items]
>   Evaluable
>   (evaluate [this]
> (reduce andr (:items this
>
> user> (evaluate (->AndList [1 2 3]))
> 3
> user> (evaluate (->AndList [1 false 3]))
> false
>
> To complete it, you'll need to add the OrList and sneak (map evaluate)

Re: First post: how to mimic a Java List with types?

2020-08-15 Thread Jack Park
My first attempt at using records (showing my ignorance here) is found in
this gist
https://gist.github.com/KnowledgeGarden/0f6ce01ed9300d4f9bd0ee0c61e3d91b

It fails with this error (which doesn't give very good google)

Syntax error macroexpanding clojure.core/defn at (cljtest/core.clj:123:1).
>   - failed: vector? at: [:fn-tail :arity-1 :params] spec:
> :clojure.core.specs.alpha/param-list
>   - failed: (or (nil? %) (sequential? %)) at: [:fn-tail :arity-n :bodies]
> spec: :clojure.core.specs.alpha/params+body
>

I wonder what I am missing.
Thanks in advance for ideas.

-Jack

On Sat, Aug 15, 2020 at 4:18 PM Jack Park  wrote:

> Brandon!
>
> That just might be the idea I needed. Thank you.
>
> Film at 11...
>
> On Sat, Aug 15, 2020 at 2:28 PM Brandon R  wrote:
>
>> Hey Jack,
>>
>> Just been a fly on the wall for this convo, and aside from offering a
>> specific solution, which others have done, I'm pretty certain this can be
>> done with just protocols and records. Make a record (like your type) that
>> implements the two protocols (like your interfaces). You could achieve your
>> desired functionality without records and protocols but what you describe
>> sounds like a fitting case for them.
>>
>> Members in such lists can be either other evaluable lists, or they can be
>>> evaluable objects which perform computations
>>>
>>
>> A simple Clojure list/vector can hold any type of data you put into it.
>> So your record can hold a vector of these things, which can be represented
>> as Clojure data structure (lists / maps / etc).
>>
>> You say you *need* to construct a type, but I urge you to challenge this
>> assumption, again and again if needed. I think it's natural to think you
>> need a type because of coming from Java/OOP land, especially if you were
>> there a long time. Old patterns die hard?
>>
>> I could be wrong though. :)
>>
>>
>> My 2 cents,
>> Brandon
>>
>> On Sat, Aug 15, 2020 at 12:42 PM Jack Park 
>> wrote:
>>
>>> Hi Erik,
>>>
>>> I think that teasing things apart helps along some dimensions, but the
>>> problem I face, still thinking like a Java hacker, is that I need to put
>>> things together:
>>>
>>> I need to construct a *type*  (deftype) which honors two different
>>> interfaces, a list, and an evaluable object. I need the type because I want
>>> to create it, then add members to the list, and then one of:
>>> a) insert the object into another one (building and/or trees)
>>> b) evaluate it - when it is the root of the tree.
>>>
>>> Members in such lists can be either other evaluable lists, or they can
>>> be evaluable objects which perform computations - even with side effects -
>>> but which return a boolean.
>>>
>>> The several ideas posted in this thread are greatly helping me to see
>>> through this situation with fresh eyes, but, thus far, nothing has
>>> convinced me to drop the goal of creating a type which is a list and
>>> evaluable, into which I can insert conjunction or disjunction evaluators.
>>>
>>> Many thanks,
>>> Jack
>>>
>>> On Sat, Aug 15, 2020 at 12:14 AM Erik Assum  wrote:
>>>
 Why not tease things apart?

 (defn eval [x] ...)

 (some eval my-list) ;; or list
 (every? eval my-list) ;; and list

 https://clojuredocs.org/clojure.core/some
 https://clojuredocs.org/clojure.core/every_q

 Now, you can make the eval function polymorphic in several ways,
 simplest is to case or cond on some property of x. You could also use
 multimethods or a protocol to achieve this.

 https://insideclojure.org/2015/04/27/poly-perf/

 Erik.
 --
 i farta

 15. aug. 2020 kl. 02:04 skrev matthew...@gmail.com <
 matthewdowne...@gmail.com>:

 

 Another option would be to do what Alex is suggesting and define and
 as a function. Just because it’s a macro in clojure.core doesn’t mean you
 can’t write your own :)

 (defn eval' [x]
   (if (map? x)
 (apply (:fn x) (:coll x))
 x))

 (defn and-list [& items]
   (let [if? (fn [x] (if x true false))
 and' (fn [& args] (every? if? args))]
 {:fn and' :coll items}))

 (eval' true) ;=> true
 (eval' false) ;=> false
 (eval' (and-list 1 2 3)) ;=> true
 (eval' (and-list 1 2 3 false)) ;=> false

 Ditto with or.
 ​
 On Friday, August 14, 2020 at 4:27:19 PM UTC-5 jack...@topicquests.org
 wrote:

> Alex,
>
> I plan to explore this idea.
> Many thanks!
>
> Jack
>
> On Fri, Aug 14, 2020 at 1:38 PM Oleksandr Shulgin <
> oleksand...@zalando.de> wrote:
>
>> 
>>
>>
>> Nevermind transducers: I've just realized that reduced can be used
>> with the normal reduce.  E.g. here's short-circuiting AND-reduction fn:
>>
>> (defn andr
>>   ([] true)
>>   ([i] i)
>>   ([r i] (let [o (and r i)]
>>(if o
>>  o
>>  (reduced o)
>>
>>