[ANN] Shrubbery 0.4.0, a stubbing, spying, and mocking library for Clojure protocols

2016-08-22 Thread Brian Guthrie
Clojure protocols are a great way to encapsulate operations with side
effects, but suffer from a lack of general test tooling. Shrubbery provides
a small set of basic building blocks for working with them.

New in this release:

– A throws function, which returns an object suitable for use with the
stub function
that throws the named exception when invoked, as so:

(defprotocol SomeProtocol
  (explode [t]))

(let [astub (shrubbery/stub SomeProtocol
  {:explode (shrubbery/throws RuntimeException "bang")})]
  (explode astub)) ;; throws RuntimeException "bang"

What Shrubbery provides:

 * stub, which accepts a variable list of protocols and a optional hashmap
of simple value implementations and returns an object that reifies all
given protocols;
 * spy, which accepts an object with at least one protocol implementation
and returns a new implementation that tracks the number of times each of
its members were called;
 * mock, which wraps a stub in a spy, allowing callers to supply basic
function implementations and assert against those calls; and
 * calls/received?, which in conjunction with the Matcher protocol provide
a way to query spies and assert against their state.

Shrubbery is test-framework-agnostic, avoids altering runtime state to the
degree possible, and uses no macros. It supports Clojure versions 1.5-1.8;
I haven't yet tested with 1.9. It should work nicely with automated
refactoring operations like rename-function.

https://github.com/bguthrie/shrubbery

[com.gearswithingears/shrubbery "0.4.0"]


Cheers,

Brian

-- 
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: [ANN] Shrubbery 0.3.0, a stubbing, spying, and mocking library for Clojure protocols

2015-10-06 Thread Brian Guthrie
On Tue, Oct 6, 2015 at 6:16 AM, Atamert Ölçgen  wrote:

> It would be great if multiple return values for multiple calls were
> supported. First use case it something like an iteration, calling some
> protocol method repeatedly (possibly with different inputs). Another use
> case is just calling it with different inputs, expecting different outputs.
> Something like (add (square x) (square y)).
>

That's an excellent suggestion; it's not something I've needed yet but it's
a common enough use-case. It should be easy enough to riff on stubs, though
trickier to set up call-based return values; I'll think on it. Thanks for
the feedback.

Cheers,

Brian

-- 
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: [ANN] Shrubbery 0.3.0, a stubbing, spying, and mocking library for Clojure protocols

2015-10-05 Thread Brian Guthrie
Great to hear! Let me know if there are any questions I can answer.
Feedback gratefully accepted.

Cheers,

Brian

On Mon, Oct 5, 2015 at 11:56 AM, James Reeves <ja...@booleanknot.com> wrote:

> Very nice. I was looking for something like this.
>
> - James
>
> On 5 October 2015 at 15:14, Brian Guthrie <btguth...@gmail.com> wrote:
>
>> Clojure protocols are a great way to encapsulate operations with side
>> effects, but suffer from a lack of general test tooling. Shrubbery provides
>> a small set of basic building blocks for working with them:
>>
>>  * stub, which accepts a variable list of protocols and a optional
>> hashmap of simple value implementations and returns an object that reifies
>> all given protocols;
>>  * spy, which accepts an object with at least one protocol
>> implementation and returns a new implementation that tracks the number of
>> times each of its members were called;
>>  * mock, which wraps a stub in a spy, allowing callers to supply basic
>> function implementations and assert against those calls; and
>>  * calls/received?, which in conjunction with the Matcher protocol
>> provide a way to query spies and assert against their state.
>>
>> Shrubbery is test-framework-agnostic, avoids altering runtime state to
>> the degree possible, and uses no macros. It should work nicely with
>> refactorings like rename-function.
>>
>> https://github.com/bguthrie/shrubbery
>>
>> [com.gearswithingears/shrubbery "0.3.0"]
>>
>>
>> New in this release:
>>
>> – Support for multiple protocols in both spies and stubs.
>> – Spies attempt to automatically derive the given implementation's
>> protocols, and tracks calls to all of them. (This behavior can be
>> overridden.)
>> – Replaced all macros with plain functions. (Unfortunately, this means
>> leaning on eval in some cases.)
>>
>> Cheers,
>>
>> Brian
>>
>> --
>> 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.
>>
>
> --
> 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.
>

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


[ANN] Shrubbery 0.3.0, a stubbing, spying, and mocking library for Clojure protocols

2015-10-05 Thread Brian Guthrie
Clojure protocols are a great way to encapsulate operations with side
effects, but suffer from a lack of general test tooling. Shrubbery provides
a small set of basic building blocks for working with them:

 * stub, which accepts a variable list of protocols and a optional hashmap
of simple value implementations and returns an object that reifies all
given protocols;
 * spy, which accepts an object with at least one protocol implementation
and returns a new implementation that tracks the number of times each of
its members were called;
 * mock, which wraps a stub in a spy, allowing callers to supply basic
function implementations and assert against those calls; and
 * calls/received?, which in conjunction with the Matcher protocol provide
a way to query spies and assert against their state.

Shrubbery is test-framework-agnostic, avoids altering runtime state to the
degree possible, and uses no macros. It should work nicely with
refactorings like rename-function.

https://github.com/bguthrie/shrubbery

[com.gearswithingears/shrubbery "0.3.0"]


New in this release:

– Support for multiple protocols in both spies and stubs.
– Spies attempt to automatically derive the given implementation's
protocols, and tracks calls to all of them. (This behavior can be
overridden.)
– Replaced all macros with plain functions. (Unfortunately, this means
leaning on eval in some cases.)

Cheers,

Brian

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


[ANN] Shrubbery 0.2.0, a stubbing, spying, and mocking library for Clojure protocols

2015-05-08 Thread Brian Guthrie
Clojure protocols are a great way to encapsulate operations with side
effects, but suffer from a lack of general test tooling. Shrubbery provides
a small set of basic building blocks for working with them:

 * stub, which accepts a protocol and a hashmap of functions and returns an
implementation with those functions (functions without implementations
return nil);
 * spy, which accepts a protocol and some implementation and returns a new
implementation that tracks the number of times each of its members were
called;
 * mock, which wraps a stub in a spy, allowing callers to supply basic
function implementations and assert against those calls; and
 * received?, which in conjunction with the Matcher protocol provides a way
to query spies and mocks

Shrubbery was written with clojure.test and Cursive in mind. It should work
nicely with goodies like jump-to-reference and rename-function.

Source here: https://github.com/bguthrie/shrubbery

One major caveat is that it's heavily reliant on macros; my attempts to
reify protocols programmatically didn't work out in the end. However,
Shrubbery's macros introduce no new syntax and carry no side effects.

Feedback welcome!

Cheers,

Brian

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


Programmatic reification

2015-04-24 Thread Brian Guthrie
Hi all,

Is there a good way to reify protocols programmatically, i.e., by passing
data structures rather than dropping down into a macro? reify bottoms out
in reify*, which doesn't help much.

Thanks,

Brian

-- 
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: Programmatic reification

2015-04-24 Thread Brian Guthrie
On Fri, Apr 24, 2015 at 10:14 AM, Steven Deobald ste...@nilenso.com wrote:

 I don't have the answer for you, but I'm definitely curious what your use
 case is. Whatcha upto?


I've become a firm believer in using protocols to encapsulate operations
with side effects, but I don't know of any good test-framework-agnostic
mocking or stubbing frameworks that work with them. I don't care much for
interaction-based (mocking) tests anyway, really, and reification is simple
enough that I don't think sugar for stubs buys you much. But it seemed like
an open niche and a fun project. If I'm wrong and such a library does
exist, please let me know.

The library I'm working on doesn't attempt to perform any var replacements,
and it doesn't introduce any new syntax; it's simply a mechanism for
building fake versions of protocols, with full or partial implementations,
that can be passed into functions that require them, and whose state (e.g.,
the set of calls they've received) can be subsequently inspected. I'd
prefer to avoid macros entirely, except that I don't know of any other way
to reify on demand.

Release coming shortly.

Cheers,

Brian

-- 
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: Programmatic reification

2015-04-24 Thread Brian Guthrie
On Fri, Apr 24, 2015 at 3:51 PM, Timothy Baldridge tbaldri...@gmail.com
wrote:

 This is why I like component (https://github.com/stuartsierra/component).
 The nice thing about using this library is that it encourages you to break
 your application into self-contained components. Those components must then
 communicate via protocols, and the result is a modular system that's much
 simpler to test.


Strongly agree. I've been making much greater use of protocols since
adopting Component on a wider scale, and that's sort of the motivation here.

Brian

-- 
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: Programmatic reification

2015-04-24 Thread Brian Guthrie
Thanks for the advice, Timothy. I think this is probably much cleaner than
where I ended up, and good advice. I'll let you know how it goes.

On Fri, Apr 24, 2015 at 10:45 AM, Timothy Baldridge tbaldri...@gmail.com
wrote:

 This is a situation where I reach for eval. Construct your reify call as
 if you were inside a macro, but instead of returning data from the macro,
 call (eval form). The call to reify will be slow (and could cause permgen
 problems), but if you wrap the form in a function you can cache the
 function and avoid that problem. Something like:


 (let [cache (atom {})]
   (defn implement-at-runtime [interface-name method-name  body]
 (if-let [result (@cache [interface-name method-name body])]
   (result)
   (let [f (eval `(fn []
(reify
  ~interface-name
  (~method-name ~@body]
 (swap! cache assoc [interface-name  method-name body] f)
 (f)

 @(implement-at-runtime 'clojure.lang.IDeref 'deref '[this] 42)
 ;; returns 42

 Timothy

 On Fri, Apr 24, 2015 at 8:14 AM, Steven Deobald ste...@nilenso.com
 wrote:

 Okay, Brian. I'll bite. :)

 I don't have the answer for you, but I'm definitely curious what your use
 case is. Whatcha upto?

 Steven Deobald -- ⌀ -- nilenso.com

 On Fri, Apr 24, 2015 at 7:18 PM, Brian Guthrie btguth...@gmail.com
 wrote:

 Hi all,

 Is there a good way to reify protocols programmatically, i.e., by
 passing data structures rather than dropping down into a macro? reify
 bottoms out in reify*, which doesn't help much.

 Thanks,

 Brian

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


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




 --
 “One of the main causes of the fall of the Roman Empire was that–lacking
 zero–they had no way to indicate successful termination of their C
 programs.”
 (Robert Firth)

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


-- 
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: [ANN][book] Clojure Reactive Programming

2015-03-28 Thread Brian Guthrie
Congratulations Leo! Folks, I had an opportunity to read some advance
chapters and it looked great even then. I'm really looking forward to
reading the whole thing. Well done.

On Tue, Mar 24, 2015 at 10:25 AM, Leonardo Borges 
leonardoborges...@gmail.com wrote:

 Hi all,

 Some of you may know that I have been working on a book for the better
 part of last year.

 I'm happy to announce it has finally been published! Here's the link:
 https://www.packtpub.com/web-development/clojure-reactive-programming

 I hope you find it useful! I've had a great time putting it together!

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


-- 
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: Retrieving the namespace an expression in compiled in

2014-10-24 Thread Brian Guthrie
Depending on how deep your investment in Compojure is, I've found Silk's
ability to derive a path once defined (bidirectional routes) to be quite
handy and very clean. I also prefer its general philosophy, though the
library's in its early days and I haven't tested it extensively. However,
it does appear to provide a nice solution for the problem you're trying to
solve. https://github.com/DomKM/silk

On Thu, Oct 23, 2014 at 11:06 PM, James Reeves ja...@booleanknot.com
wrote:

 I have some code that looks like this:

 (ns foo.bar.endpoint.example
   (:require [compojure.core :refer [routes GET]]
 [duct.util.resource :as resource]))

 (defn endpoint [config]
   (routes
(GET / []
  (resource/url foo/bar/endpoint/example/index.html

 In this case the resource/url function acts the same as
 clojure.java.io/resource.

 The problem is that I'd like to remove the repetition, so I extended
 resource/url with the ability to derive the resource path from a namespace
 object.

 (defn endpoint [config]
   (routes
(GET / [] (resource/url *ns* index.html

 The problem with this approach is that the *ns* binding changes, and I
 want to fix it at compile time. I could write:

 (def this-ns *ns*)

 (defn endpoint [config]
   (routes
(GET / [] (resource/url this-ns index.html

 But it's very tempting to use the eval reader form:

 (defn endpoint [config]
   (routes
(GET / [] #=(resource/url *ns* index.html

 Or a macro:

 (defn endpoint [config]
   (routes
(GET / [] (resource/url (this-ns) index.html

 Alternatively, I could do something with a quoted symbol:

 (defn endpoint [config]
   (routes
(GET / [] (resource/url `index .html

 Or a keyword:

 (defn endpoint [config]
   (routes
(GET / [] (resource/url ::index .html

 What does everything think is the best solution?

 I must admit I'm tempted to use the eval reader, as it makes it very
 explicit as to what's happening, while at the same time being very concise.

 On the other hand, the eval reader isn't often used, and isn't actually
 documented in the reader docs, just in the *read-eval* docs.

 - James

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


-- 
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: Retrieving the namespace an expression in compiled in

2014-10-24 Thread Brian Guthrie
Oopsie daisy. Sorry, James––thanks for your hard work.

On Fri, Oct 24, 2014 at 12:59 PM, Herwig Hochleitner hhochleit...@gmail.com
 wrote:

 2014-10-24 10:20 GMT+02:00 Brian Guthrie btguth...@gmail.com:

 Depending on how deep your investment in Compojure is, I've found ...


 I'd imagine James' investment with Compojure to be quite substantial,
 given that he is its primary author ;-)

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


-- 
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: [ANN] async-sockets - work with sockets using core.async channels

2014-10-07 Thread Brian Guthrie
On Sun, Oct 5, 2014 at 11:57 PM, Zach Tellman ztell...@gmail.com wrote:

 If I'm reading this correctly, you're using non-blocking thread pools for
 blocking operations on the sockets.  Given more than N connections (last
 time I looked the thread pool's size was 42), you risk deadlock or at the
 very least poor average throughput.


I'd thought the thread pool's size was a function of your core count plus
some constant, which I believe is 42. But yes, that is a constraint, and
deadlock is a risk with too many concurrent connections. I haven't tried to
measure throughput yet but that seems like a reasonable next step. Thanks
for the code review!

-- 
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: [ANN] async-sockets - work with sockets using core.async channels

2014-10-07 Thread Brian Guthrie
On Mon, Oct 6, 2014 at 12:10 AM, adrian.med...@mail.yu.edu wrote:

 Zach makes an excellent point; I've used AsyncSocketChannels and its irk (
 http://docs.oracle.com/javase/8/docs/api/java/nio/channels/AsynchronousServerSocketChannel.html),
 with core.async in the past. Perhaps replacing your direct java.net.Sockets
 with nio classes that can be given CompletionHandlers (
 http://docs.oracle.com/javase/7/docs/api/java/nio/channels/CompletionHandler.html)
 would be a better fit.


Once I do some performance instrumentation I'll give that a shot. I admit
that I'm not familiar with all the implications of using the nio classes;
were I to switch, is it safe to continue using go blocks, or is it worth
explicitly allocating a single thread per socket?

Brian

-- 
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: For async, expose the channel directly or expose a function?

2014-10-05 Thread Brian Guthrie
Fair enough. Thanks again.

On Sat, Oct 4, 2014 at 11:49 AM, Stuart Sierra m...@stuartsierra.com
wrote:


 On Sat, Oct 4, 2014 at 12:31 AM, Brian Guthrie btguth...@gmail.com
 wrote:

 But I'm troubled by the idea of accepting channels as arguments, even
 though there's a lot to be said for consumer control of buffer sizes (to
 say nothing of providing potential fakes for test purposes). In that
 scenario you'd essentially be *mutating* the input when you set up the
 go-loop that feeds (or takes input from) the channel, yes? So in effect
 they become out-params.



 Once you start messing around with channels, you're no longer in the
 pure-functional business. Channels aren't values. Things which use channels
 are processes, not functions.

 -S

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


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


[ANN] async-sockets - work with sockets using core.async channels

2014-10-05 Thread Brian Guthrie
Hi all,

I'm releasing a little library for working with sockets. Feedback and pull
requests gratefully appreciated.

The skinny
---

This library allows you to create socket servers and socket clients and
interact with them asynchronously using channels. Servers return a record
with a :connections field, a channel which yields one socket per incoming
connection. Clients return the same socket record. Socket records each have
an :in and :out channel each which allow you to receive and send data
respectively on a line-by-line basis. The raw java.net.Socket is also
available (as :socket).

Servers and clients are defined using the Component framework and must be
explicitly started using (component/start server-or-client), though
sockets will clean up after themselves if they are terminated for some
reason.

Further information is available on Github here:
https://github.com/bguthrie/async-sockets

Releases
--

This is the first release, which I've tagged for now as 0.0.1-SNAPSHOT.
Leiningen dependency: [com.gearswithingears/async-sockets 0.0.1-SNAPSHOT].

If this is useful to you, please let me know, but any and all feedback is
great.

Happy hacking,

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


For async, expose the channel directly or expose a function?

2014-10-03 Thread Brian Guthrie
Hi all,

I'm assembling a library for working with sockets asynchronously (both as a
server and a client) and was wondering if there was a widely-accepted way
of handling channels. The rough idea is that each socket gets two channels,
in and out, receiving data in the former and using the latter to write it
out.

What I'm asking is whether it's preferable to set up a construction
function and return a record (or map) with :in and :out keys, with the
expectation that consumers can manipulate those channels directly, or
expose functions like read-line and write-line that returns a channel which
yields and closes once on completion.

Essentially, it's the difference between writing:

  (let [sock (socket-client localhost 1024)
 line (async/! (:in sock))]
  ...)

or writing:

  (let [sock (socket-client localhost 1024)
 line (async/! (read-line sock))]
  ...)

The disadvantage to the latter approach is that it breaks the channel
contract: channels should return nil on closure. With single-yield
channels, detecting nil closure is tiresome: you intentionally return an
empty channel. And though the function name is nice and clear, it seems
like a lot of effort to put up a nice facade, especially if folks are
already comfortable managing channels directly.

Any thoughts?

Thanks,

Brian

-- 
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: For async, expose the channel directly or expose a function?

2014-10-03 Thread Brian Guthrie
Thanks for the feedback! I buy that direct access to the channels provides
more transformative power, so I'll stick with that. But I'm troubled by the
idea of accepting channels as arguments, even though there's a lot to be
said for consumer control of buffer sizes (to say nothing of providing
potential fakes for test purposes). In that scenario you'd essentially be
*mutating* the input when you set up the go-loop that feeds (or takes input
from) the channel, yes? So in effect they become out-params. Doable but odd.

Brian

On Fri, Oct 3, 2014 at 7:00 PM, Stuart Sierra the.stuart.sie...@gmail.com
wrote:

 You generally provide more power and flexibility to consumers by handing
 them channels. That way the consumer can use things like transducers and
 pipelines.

 For maximum flexibility, allow the consumer to *pass in* the channels to
 be used for input / output. That way the consumer gets to decide about
 buffering.

 -S




  Friday, October 3, 2014 12:06:05 PM UTC-4, Brian Guthrie wrote:

 Hi all,

 I'm assembling a library for working with sockets asynchronously (both as
 a server and a client) and was wondering if there was a widely-accepted way
 of handling channels. The rough idea is that each socket gets two channels,
 in and out, receiving data in the former and using the latter to write it
 out.

 What I'm asking is whether it's preferable to set up a construction
 function and return a record (or map) with :in and :out keys, with the
 expectation that consumers can manipulate those channels directly, or
 expose functions like read-line and write-line that returns a channel which
 yields and closes once on completion.

 Essentially, it's the difference between writing:

   (let [sock (socket-client localhost 1024)
  line (async/! (:in sock))]
   ...)

 or writing:

   (let [sock (socket-client localhost 1024)
  line (async/! (read-line sock))]
   ...)

 The disadvantage to the latter approach is that it breaks the channel
 contract: channels should return nil on closure. With single-yield
 channels, detecting nil closure is tiresome: you intentionally return an
 empty channel. And though the function name is nice and clear, it seems
 like a lot of effort to put up a nice facade, especially if folks are
 already comfortable managing channels directly.

 Any thoughts?

 Thanks,

 Brian

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


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