Re: Blocking behavior of >!! ?

2019-05-20 Thread Brian Beckman
Thanks everyone for your answers. I understand much better now. I just had 
to make up some words like "rendezvous" and "pseudothread" to help me piece 
together these implicit concepts.

On Sunday, May 19, 2019 at 10:33:07 AM UTC-7, Brian Beckman wrote:
>
> The documentation for >!! reads:
>
> -
> clojure.core.async/>!!
> ([port val])
>   puts a val into port. nil values are not allowed. Will block if no
>   buffer space is available. Returns true unless port is already closed.
>
>
> I have a case where I believe that the channel has no buffer, I park a 
> "pseudothread" in a go block reading off that channel via  (lexically, not temporally), put to the unbuffered channel via >!!:
>
> (let [c (chan) ;; NO BUFFER!
>   d (go (   e (>!! c 42)] ;; blocking write to c, will unpark c's pseudothread
> (println {:c-coughs-up '(this will hang (   :d-coughs-up (   :what's-ee})
> (close! c) (close! d))
>
> {:c-coughs-up (this will hang (
>
> This case leads me to wonder whether the documentation might read
>
>  >!! will block if there is no buffer space available *and* if there is 
> no *rendezvous *available, that is, no pseudothread parked waiting for 
> but it's more likely that I completely misunderstand core.async because I 
> just made up the notion of a pseudothread in my struggle to understand!
>
>
>
>

-- 
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/0b243161-9598-490e-ad81-93d53a76a21b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Blocking behavior of >!! ?

2019-05-20 Thread Brian Beckman
Thanks, Thomas. I shouldn't have included the quoted code about (!! c 42) doesn't block. 

The following is an attempt to clarify my question. I first (go (!! c 42), 
and then (!! c 42) 
will block "if there is no buffer space available," and the documentation 
does not specify any other conditions. Well, I created c with no buffer 
space, so, (>!! c 42) must block unless something else "makes buffer space 
available," assuming the documentation is correct. The only other 
interaction with c that could possibly be alive at the time when I do (>!! 
c 42), is (go (!! c 42) 
should block because there is no buffer available. 

On Sunday, May 19, 2019 at 1:48:16 PM UTC-7, Thomas Heller wrote:
>
> ( by the first go (running in a different thread). So it is blocking until 
> something puts another value into c. Since nothing ever does your program 
> hangs.
>
> If it helps you can read "go" as "please run this somewhere else, possibly 
> at a different time" and let the current thread continue after the go.
>
> I can't explain this very well but the documentation aspect is accurate.
>
> On Sunday, May 19, 2019 at 7:33:07 PM UTC+2, Brian Beckman wrote:
>>
>> The documentation for >!! reads:
>>
>> -
>> clojure.core.async/>!!
>> ([port val])
>>   puts a val into port. nil values are not allowed. Will block if no
>>   buffer space is available. Returns true unless port is already closed.
>>
>>
>> I have a case where I believe that the channel has no buffer, I park a 
>> "pseudothread" in a go block reading off that channel via > (lexically, not temporally), put to the unbuffered channel via >!!:
>>
>> (let [c (chan) ;; NO BUFFER!
>>   d (go (>   e (>!! c 42)] ;; blocking write to c, will unpark c's pseudothread
>> (println {:c-coughs-up '(this will hang (>   :d-coughs-up (>   :what's-ee})
>> (close! c) (close! d))
>>
>> {:c-coughs-up (this will hang (>
>>
>> This case leads me to wonder whether the documentation might read
>>
>>  >!! will block if there is no buffer space available *and* if there is 
>> no *rendezvous *available, that is, no pseudothread parked waiting for > .
>>
>> but it's more likely that I completely misunderstand core.async because I 
>> just made up the notion of a pseudothread in my struggle to understand!
>>
>>
>>
>>

-- 
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/fe9fc48c-d651-434d-8743-0045438291f1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Blocking behavior of >!! ?

2019-05-19 Thread Brian Beckman
The documentation for >!! reads:

-
clojure.core.async/>!!
([port val])
  puts a val into port. nil values are not allowed. Will block if no
  buffer space is available. Returns true unless port is already closed.


I have a case where I believe that the channel has no buffer, I park a 
"pseudothread" in a go block reading off that channel via !!:

(let [c (chan) ;; NO BUFFER!
  d (go (!! c 42)] ;; blocking write to c, will unpark c's pseudothread
(println {:c-coughs-up '(this will hang (!! will block if there is no buffer space available *and* if there is no 
*rendezvous *available, that is, no pseudothread parked waiting for 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/ef62965f-6132-4f18-9bb8-3d569f10dbdc%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Seeking critique of "pattern" in clojure.spec (LONG)

2017-04-11 Thread Brian Beckman
I should have called them "blueberries" instead of the more provocative 
"virtual times."  I was trying to go from an abstract mathematical 
definition to a formalization in Clojure. Eventually, virtual times will be 
part of a discrete-even simulation platform, but it's too early to say much 
about that now. I'm just setting up the pylons at present.

Clojure number? excluding NaN will do for now: they have the required 
semantics at the limits and they're comparable amongst Double, Integer, 
Fraction, etc. Later, I may need a density axiom ("between any two finite 
blueberries there is another blueberry") and that's not true for Doubles. 
At that point I will definitely look back at your excellent answer and 
consider s/fdef's.

On Monday, April 10, 2017 at 10:15:19 PM UTC-7, Didier wrote:
>
> Here it is adapted to use a deftype: 
> https://gist.github.com/didibus/2ccd608ed9d226039f944b02a10f9ad5
>
> I gather from your solution that "orchestra" is not needed to spec :ret 
>> types?
>>
>
> It is not. The return spec will be used during st/check. If you want the 
> return spec to be validated outside of st/check though, than you need 
> Orchestra.
>
> I shall have to read up on deftype versus defrecord.
>>
>
> I recommend the clojure.org explanation: 
> https://clojure.org/reference/datatypes#_deftype_and_defrecord
> In a nutshell, deftype is a blank Java class, defrecord is an extended 
> PersistentHashMap.
>
> I am not sure why you need a VirtualTime, and what it will be doing, so I 
> can't really comment on which solution is best. As James said, it appears 
> you might be creating something that behaves the same way Double does? 
> Double already has positive and negative infinity and NaN:
>
> (/ 0.0 0.0) ; NaN
> (* 99e 99e) ; Infinity
> (* 99e -99e) ; -Infinity
> (< Double/NEGATIVE_INFINITY Double/POSITIVE_INFINITY) ; true
> (= Double/NEGATIVE_INFINITY Double/POSITIVE_INFINITY) ; false
>
> I'd suggest, if you need Double, use Double. If you need something close 
> to Double, and you can build on top of it, simpler to go with the style of 
> my first gist. If you can't build on top of double, deftype is probably 
> what you want.
>
> On Monday, 10 April 2017 21:41:35 UTC-7, Brian Beckman wrote:
>>
>> Wow... that's a comprehensive solution, Didier :) Bravo! It's a good 
>> lesson for s/fdef, which I haven't yet studied. I gather from your solution 
>> that "orchestra" is not needed to spec :ret types?
>>
>> As to semantics, on the one hand, I can spec ::virtual-time as a light 
>> overlay over Double and risk conflation of ordinary operators like < <= = 
>> etc. On the other hand, I have several options for full protection. I shall 
>> have to read up on deftype versus defrecord.
>>
>

-- 
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.
For more options, visit https://groups.google.com/d/optout.


Re: Seeking critique of "pattern" in clojure.spec (LONG)

2017-04-10 Thread Brian Beckman
Wow... that's a comprehensive solution, Didier :) Bravo! It's a good lesson for 
s/fdef, which I haven't yet studied. I gather from your solution that 
"orchestra" is not needed to spec :ret types?

As to semantics, on the one hand, I can spec ::virtual-time as a light overlay 
over Double and risk conflation of ordinary operators like < <= = etc. On the 
other hand, I have several options for full protection. I shall have to read up 
on deftype versus defrecord.

-- 
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.
For more options, visit https://groups.google.com/d/optout.


Re: Seeking critique of "pattern" in clojure.spec (LONG)

2017-04-10 Thread Brian Beckman
James -- just the kind of simplification I was looking for! In fact, I 
think the following will do everything I need --- generate numbers avoiding 
only NaN (which isn't equal to itself, nor less than anything)

(s/def ::virtual-time
  (s/with-gen
(s/and
 number? #(not (Double/isNaN %)))
;; We'd like most values generated in tests to be finite, with the
;; occasional infinity for spice. Adjust these frequencies to taste.
#(gen/frequency [[98 (s/gen number?)]
 [ 1 (gen/return Double/NEGATIVE_INFINITY)]
 [ 1 (gen/return Double/POSITIVE_INFINITY)]])))



-- 
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.
For more options, visit https://groups.google.com/d/optout.


Re: Seeking critique of "pattern" in clojure.spec (LONG)

2017-04-10 Thread Brian Beckman
These are good comments that give me things to think about. I'm grateful.
* The pattern concerned me because (1) it was just the first thing I came 
up with, so not sure there wasn't a better way staring me in the face (2) I 
didn't see any clearly better alternatives, so not sure whether I just 
don't know enough Clojure (3) it intuitively felt heavyweight with at least 
four "complected" language features.
* Understood about polymorphism. In my real app, I have a lot of it, but I 
thought I would use protocols & records even when I don't have polymorphism 
just for uniformity of style: one way to express my "testable types." 
* You've pointed out an overlap between two different ways to specify 
structure: (A) requiring keys via records and (B) requiring keys using 
specs over ordinary maps. Starting with records, I sensed that some of my 
specs were actually vapid, and now you've told me why.  
* I think experimenting with mere (collections of) functions over mere maps 
with structure enforced by specs is a good idea. I'll try it and "weigh" it 
against this alternative.


On Monday, April 10, 2017 at 1:13:49 PM UTC-7, Didier wrote:
>
> I think this pattern is fine.
>
> What specifically about it annoys you?
>
> You could do it without records, but then you wouldn't be creating a type. 
> Do you really need a type?
>
> The advantage of types in Clojure are that they let you do polymorphic 
> dispatch of them. So they are useful if you have one function which you 
> want to reuse for many types.
>
> In your case, I'm not seeing other records implementing the protocol. So 
> it doesn't seem you need polymorphic dispatch on type. So maybe you can 
> drop the protocol.
>
> Records are useful if you need a map with guaranteed keys. Spec makes this 
> feature less useful, because you can now spec a map and test that it always 
> has the right keys when used. If you have a record, a fn that works over 
> that record just needs to check the argument has the type of record, and it 
> knows the keys exist. If you have a map instead, the fn would need to check 
> the keys exist.
>
> Records don't support unions, all keys must exist. In your case, you want 
> unions, a map with keys x,y or z. So if you use a record, some keys will 
> always have nil value. So, again, you might be better served by a map.
>
> Recap. Protocols if you want a common interface accross multiple types. 
> Records if you want to create a map with guaranteed keys, which will 
> identify itself as a named java type.
>
> Your spec can't really be made shorter, since they need custom gens.
>
> If I was you, I'd experiment with functions over maps. One thing to 
> consider is that specs are structural types, not nominal. So if you spec a 
> map, it describes its structure. A function says I take a structure of that 
> shape, if you give me anything that conforms, I can successfully do my job. 
> The shape itself has no known runtime name.
>
>

-- 
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.
For more options, visit https://groups.google.com/d/optout.


Seeking critique of "pattern" in clojure.spec (LONG)

2017-04-10 Thread Brian Beckman
"I apologize for the length of this post ..."  Blaise Pascal?

I am seeking critique of a certain "programming pattern" that's arisen 
several times in a project. I want testable types satisfying a protocol, 
but the pattern I developed "feels" heavyweight, as the example will show, 
but I don't know a smaller way to get what I want. The amount of code I 
needed to formalize and test my specs "feels" like too much. In particular, 
the introduction of a defrecord just to support the protocol doesn't "feel" 
minimal. The defrecord provides a constructor with positional args — of 
dubious utility — especially for large records, but otherwise acts like a 
hashmap. Perhaps there is a way to bypass the defrecord and directly use a 
hashmap?

Generally, I am suspicious of "programming patterns," because I believe 
that an apparent need for a programming pattern usually means one of two 
things:

   1. 
   
   The programming language doesn't directly support some reasonable need, 
   and that's not usually the case with Clojure
   2. 
   
   Ignorance: I don't know an idiomatic way to do what I want.
   
There is a remote, third possibility, that "what I want" is stupid, 
ignorant, or otherwise unreasonable. 
Here is what I settled on: quadruples of protocol, defrecord, specs and 
tests to fully describe and test types in my application:

   1. 
   
   a protocol to declare functions that certain types must implement
   2. 
   
   at least one defrecord to implement the protocol
   3. 
   
   a spec to package checks and test generators
   4. 
   
   tests to, well, test them
   
For a small example (my application has some that are much bigger), 
consider a type that models "virtual times" as numbers-with-infinities. 
Informally, a "virtual time" is either a number or one of two distinguished 
values for plus and minus infinity. Minus infinity is less than any virtual 
time other than minus infinity. Plus infinity is greater than any virtual 
time other than plus infinity." I'll write a protocol, a defrecord, a spec, 
and a couple of tests for this type. 

In the actual code, the elements come in the order of protocol, defrecord, 
spec, and tests because of cascading dependencies. For human consumption, 
I'll "detangle" them and present the spec first:

(s/def ::virtual-time  (s/with-gen(s/and ; idiom for providing a 
"conformer" function below (s/or  :minus-infinity #(vt-eq % 
:vt-negative-infinity) ; see the protocol for "vt-eq"  :plus-infinity  
#(vt-eq % :vt-positive-infinity)  :number #(number? (:vt %))) 
(s/conformer second))  ; strip off redundant conformer tag
#(gen/frequency [[98 vt-number-gen] ; generate mostly numbers ...   
  [ 1 vt-negative-infinity-gen] ; ... with occasional infinities
 [ 1 vt-positive-infinity-gen]])))

That should be self-explanatory given the following definitions:

(def vt-number-gen  (gen/bind   (gen/large-integer)   (fn [vt] (gen/return 
(virtual-time. vt) ; invoke constructor ... heavyweight?​(def 
vt-negative-infinity-gen  (gen/return (virtual-time. 
:vt-negative-infinity)))​(def vt-positive-infinity-gen  (gen/return 
(virtual-time. :vt-positive-infinity)))

The tests use the generators and a couple of global variables:

(def vt-negative-infinity (virtual-time. :vt-negative-infinity))(def 
vt-positive-infinity (virtual-time. :vt-positive-infinity))​(defspec 
minus-infinity-less-than-all-but-minus-infinity  100  (prop/for-all   [vt 
(s/gen :pattern-mve.core/virtual-time)]   (if (not= (:vt vt) 
:vt-negative-infinity) (vt-lt vt-negative-infinity vt) ; see the protocol 
for def of "vt-lt" true)))​(defspec plus-infinity-not-less-than-any  100  
(prop/for-all   [vt (s/gen :pattern-mve.core/virtual-time)]   (not (vt-lt 
vt-positive-infinity vt

The protocol specifies the comparison operators "vt-lt" and "vt-le." A 
defrecord to implement it should now be obvious, given understanding of how 
they're used above:

(defprotocol VirtualTimeT  (vt-lt [this-vt that-vt])  (vt-le [this-vt that-vt]) 
 (vt-eq [this-vt that-vt]))​(defn -vt-compare-lt [this-vt that-vt]  (case (:vt 
this-vt):vt-negative-infinity(case (:vt that-vt)  
:vt-negative-infinity false  #_otherwise true)​:vt-positive-infinity
false​;; otherwise: this-vt is a number.(case (:vt that-vt)  
:vt-positive-infinity true  :vt-negative-infinity false  #_otherwise (< 
(:vt this-vt) (:vt that-vt)​(defrecord virtual-time [vt]  VirtualTimeT  
(vt-lt [this that] (-vt-compare-lt this that))  (vt-eq [this that] (= this 
that))  (vt-le [this that] (or (vt-eq this that) (vt-lt this that

Please see a runnable project here 
https://github.com/rebcabin/ClojureProjects/tree/working/pattern-mve 

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

Re: Priority Map with efficient search on values?

2017-04-08 Thread Brian Beckman
"Much appreciated" to all answerers. Looks like priority-map has maps in 
both directions that I can use quickly. I'll write a protocol with the API 
I need, implement it with priority-map's non-superficial features to get 
going, then investigate more advanced data structures if / when I need to.

On Friday, April 7, 2017 at 10:55:44 PM UTC-7, Brian Beckman wrote:
>
> I have found a few data types in Clojure that support search and priority 
> queues. In particular, I found 
>
> Priority Maphttps://github.com/clojure/data.priority-map
> PSQhttps://goo.gl/Dw4gkV
> data.avlhttps://goo.gl/e07q7H
>
> I would be grateful for a few clarifying words on whether any of these can 
> meet my requirements out-of-the-box before I begin a deep-dive. Forgive me 
> for being a bit lazy (actually, just in a hurry), but I thought I'd check 
> whether someone knows an answer for me off-the-cuff.
>
> I need collections of [k v] pairs supporting efficient peek, pop, get, and 
> subseq-style search on either the key space or on the value space. I need 
> all operations on just one of the two spaces.
>
> Priority map supports efficient peek and pop of the value space on its API 
> surface, but I don't see a get subseq (or rsubseq) or other way to quickly 
> search the value space on the API surface. The comments in the source 
> suggest that there is an auxiliary inverse sorted map from values to keys. 
> The supported "get" operation seems to operate on the key space, but I 
> could use one on the value space (see line 313 of https://goo.gl/qhfXKL). 
> Perhaps that inverse map easy to get at, in which case I'll be done.
>
> PSQ supports peek and pop on values, and efficient search on keys, 
> according to its documentation. Do I read that correctly?
>
> I have not read the documentation for data.avl deeply enough to know 
> whether it will do my job out-of-the box. But I am sure I could build what 
> I need on top of AVL trees, RB trees, 2-3 trees, splay trees, etc. I'm just 
> looking to save myself work (and use tested software).
>

-- 
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.
For more options, visit https://groups.google.com/d/optout.


Priority Map with efficient search on values?

2017-04-07 Thread Brian Beckman
I have found a few data types in Clojure that support search and priority 
queues. In particular, I found 

Priority Maphttps://github.com/clojure/data.priority-map
PSQhttps://goo.gl/Dw4gkV
data.avlhttps://goo.gl/e07q7H

I would be grateful for a few clarifying words on whether any of these can 
meet my requirements out-of-the-box before I begin a deep-dive. Forgive me 
for being a bit lazy (actually, just in a hurry), but I thought I'd check 
whether someone knows an answer for me off-the-cuff.

I need collections of [k v] pairs supporting efficient peek, pop, get, and 
subseq-style search on either the key space or on the value space. I need 
all operations on just one of the two spaces.

Priority map supports efficient peek and pop of the value space on its API 
surface, but I don't see a get subseq (or rsubseq) or other way to quickly 
search the value space on the API surface. The comments in the source 
suggest that there is an auxiliary inverse sorted map from values to keys. 
The supported "get" operation seems to operate on the key space, but I 
could use one on the value space (see line 313 of https://goo.gl/qhfXKL). 
Perhaps that inverse map easy to get at, in which case I'll be done.

PSQ supports peek and pop on values, and efficient search on keys, 
according to its documentation. Do I read that correctly?

I have not read the documentation for data.avl deeply enough to know 
whether it will do my job out-of-the box. But I am sure I could build what 
I need on top of AVL trees, RB trees, 2-3 trees, splay trees, etc. I'm just 
looking to save myself work (and use tested software).

-- 
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.
For more options, visit https://groups.google.com/d/optout.