Thanks everyone for your input. I just wanted to say that I have an initial
version of the library available at my github
<https://github.com/johanhaleby/stub-http> page if anyone is interested.

On Sat, Mar 12, 2016 at 3:43 PM, Timothy Baldridge <tbaldri...@gmail.com>
wrote:

> "Idiomatic" is always a hard word to define, and I think some of the
> points made here are good, but let me also provide a few guidelines I try
> to abide by when writing an API:
>
> Start with data, preferably hash maps. At some point your API will be
> consumed by someone else's program. Macros make it hard to compose api
> calls in a sane matter using code. So stick with hash maps and pure data.
> Something like the following:
>
> {:host "foo.bar.com"
>  :port 80
>  :path "/some/path/i/want"
>  :params {:name :value :key :value2}}
>
> Now if it comes time to modify/process/compose this request we can use
> normal Clojure functions like assoc/conj to build this request map. Of
> course, using this approach normally results in a explosion of data, so
> pretty it up with helper functions:
>
> (make-request-map "http://foo.bar.com/some/path/i/want"; {:name :value})
>
> The key here, is that these helper functions should emit the data you
> specified in the first step.
>
> And finally, write macros as a last resort to pretty up the user
> experience even further. In short:
>
> 1) Start with data to allow clojure code to easily access your API
> 2) Make generating that data simpler by writing helper functions to
> generate data
> 3) (Optionally) Write a DSL to make user interaction easier.
>
> Timothy
>
> On Sat, Mar 12, 2016 at 6:41 AM, Johan Haleby <johan.hal...@gmail.com>
> wrote:
>
>> Thanks a lot for your support and insights. I'm going to rewrite it to
>> use "with-open" as we speak.
>>
>> On Sat, Mar 12, 2016 at 2:37 PM, Marc Limotte <mslimo...@gmail.com>
>> wrote:
>>
>>> Look at the source for the clojure.core with-open macro.  In the repl:
>>> `(source with-open)`.
>>>
>>> I think Gary is right.  with-open does exactly what you need, I should
>>> have thought of that, and you should probably use it.  But if you want to
>>> get your version working, trying to understand what the with-open macro is
>>> doing.  Your implementation can be simpler because you only have one
>>> explicit binding.  Essentially you'll create a let as a backquoted form and
>>> then splice in the explicit symbol from the user:
>>>
>>>
>>>    `(let [~sym ...server-instance-or-uri...] ... )
>>>
>>>
>>> marc
>>>
>>>
>>>
>>>
>>> On Sat, Mar 12, 2016 at 1:57 AM, Johan Haleby <johan.hal...@gmail.com>
>>> wrote:
>>>
>>>>
>>>>
>>>> On Wed, Mar 9, 2016 at 7:32 PM, Marc Limotte <mslimo...@gmail.com>
>>>> wrote:
>>>>
>>>>> With the macro approach, they don't need to escape it.
>>>>>
>>>>
>>>> Do you know of any resources of where I can read up on this? I have the
>>>> macro working with an implicit "uri" generated but I don't know how to make
>>>> it explicit (i.e. defined by the user) the way you proposed.
>>>>
>>>>
>>>>>
>>>>> On Wed, Mar 9, 2016 at 12:52 PM, Johan Haleby <johan.hal...@gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Thanks a lot for your support Marc, really appreciated.
>>>>>>
>>>>>> On Wed, Mar 9, 2016 at 5:33 PM, Marc Limotte <mslimo...@gmail.com>
>>>>>> wrote:
>>>>>>
>>>>>>> Yes, I was assuming the HTTP calls happen inside the
>>>>>>> with-fake-routes! block.
>>>>>>> I missed the part about the random port.  I se 3 options for that:
>>>>>>>
>>>>>>> *Assign a port, rather than random*
>>>>>>>
>>>>>>> (with-fake-routes! 9999 ...)
>>>>>>>
>>>>>>>
>>>>>>> But then, of course, you have to worry about port already in use.
>>>>>>>
>>>>>>> *An atom*
>>>>>>>
>>>>>>> (def the-uri (atom nil))
>>>>>>> (with-fake-routes! the-uri
>>>>>>>   ...
>>>>>>>   (http/get @the-uri "/x"))
>>>>>>>
>>>>>>> *A macro*
>>>>>>>
>>>>>>> A common convention in Clojure would be to pass it a symbol (e.g.
>>>>>>> `uri` that is bound by the macro), rather implicitly creating `uri`.
>>>>>>>
>>>>>>> (with-fake-routes! [uri option-server-instance]
>>>>>>>
>>>>>>>     route-map
>>>>>>>
>>>>>>>     (http/get uri "/x"))
>>>>>>>
>>>>>>>
>>>>>> Didn't know about this convention so thanks for the tip. But is your
>>>>>> snippet above actually working code or does the user need escape "uri" 
>>>>>> and "
>>>>>> option-server-instance" using a single-quotes, i.e.
>>>>>>
>>>>>> (with-fake-routes! [*'*uri *'*option-server-instance] ...)
>>>>>>
>>>>>>
>>>>>>>
>>>>>>> or, with a pre-defined server
>>>>>>>
>>>>>>> (def fake-server ...)
>>>>>>> (with-fake-routes!
>>>>>>>
>>>>>>>     route-map
>>>>>>>
>>>>>>>     (http/get (:uri fake-server) "/x"))
>>>>>>>
>>>>>>>
>>>>>>> marc
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Wed, Mar 9, 2016 at 1:00 AM, Johan Haleby <johan.hal...@gmail.com
>>>>>>> > wrote:
>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On Wed, Mar 9, 2016 at 6:20 AM, Johan Haleby <
>>>>>>>> johan.hal...@gmail.com> wrote:
>>>>>>>>
>>>>>>>>> Thanks for your feedback, exactly what I wanted.
>>>>>>>>>
>>>>>>>>> On Tuesday, March 8, 2016 at 3:16:02 PM UTC+1, mlimotte wrote:
>>>>>>>>>>
>>>>>>>>>> I don't think you need a macro here.  In any case, I'd avoid
>>>>>>>>>> using a macro as late as possible.  See how far you get with just
>>>>>>>>>> functions, and then maybe at the end, add one macro if you 
>>>>>>>>>> absolutely need
>>>>>>>>>> it to add just a touch of syntactic sugar.
>>>>>>>>>>
>>>>>>>>>> routes should clearly be some sort of data-structure, rather than
>>>>>>>>>> side-effect setter functions.  Maybe this:
>>>>>>>>>>
>>>>>>>>>> (with-fake-routes!
>>>>>>>>>>   optional-server-instance
>>>>>>>>>>   route-map)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>> Hmm now that I come to think of it I don't see how this would
>>>>>>>> actually work unless you also perform the HTTP request from inside the
>>>>>>>> scope of  with-fake-routes!, otherwise the server instance would
>>>>>>>> be closed before you get the chance to make the request. Since you
>>>>>>>> make an actual HTTP request you need access to the URI generated when
>>>>>>>> starting the fake-server instance (at least if the port is chosen
>>>>>>>> randomly). So either I suppose you would have to do like this
>>>>>>>> (which requires a macro?):
>>>>>>>>
>>>>>>>> (with-fake-routes!
>>>>>>>>   {"/x" {:status 200 :content-type "application/json" :body (slurp
>>>>>>>> (io/resource "my.json"))}}
>>>>>>>>   ; Actual HTTP request
>>>>>>>>   (http/get uri "/x"))
>>>>>>>>
>>>>>>>> where "uri" is created by the  with-fake-routes! macro *or* we
>>>>>>>> could return the generated fake-server. But if so
>>>>>>>> with-fake-routes! cannot automatically close the fake-server instance
>>>>>>>> since we need the instance to be alive when we make the call to the
>>>>>>>> generated uri. I suppose it would have to look something like this:
>>>>>>>>
>>>>>>>> (let [fake-server (with-fake-routes! {"/x" {:status 200
>>>>>>>> :content-type "application/json" :body (slurp (io/resource 
>>>>>>>> "my.json"))}})]
>>>>>>>> (http/get (:uri fake-server) "/x")
>>>>>>>> (shutdown! fake-server))
>>>>>>>>
>>>>>>>> If so I think that the second option is unnecessary since then you
>>>>>>>> might just go with:
>>>>>>>>
>>>>>>>> (with-fake-routes!
>>>>>>>>   *required*-server-instance
>>>>>>>>   route-map)
>>>>>>>>
>>>>>>>> instead of having two options. But then we loose the niceness of
>>>>>>>> having the server instance be automatically created and stopped for us?
>>>>>>>>
>>>>>>>>
>>>>>>>>>> Where optional-server-instance, if it exists is, an object
>>>>>>>>>> returned by (fake-server/start!).  If optional-server-instance is
>>>>>>>>>> not passed in, then with-fake-routes! creates it's own and is
>>>>>>>>>> free to call (shutdown!) on it automatically. And route-map is a
>>>>>>>>>> Map of routes:
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>> {
>>>>>>>>>> "/x"
>>>>>>>>>>   {:status 200 :content-type "application/json" :body (slurp
>>>>>>>>>> (io/resource "my.json"))}
>>>>>>>>>> {:path "/y" :query {:q "something")}}
>>>>>>>>>>   {:status 200 :content-type "application/json" :body (slurp
>>>>>>>>>> (io/resource "my2.json"))}
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>> +1. I'm gonna go for this option.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Also, at the risk of scope creep, I could foresee wanting the
>>>>>>>>>> response to be based on the input instead of just a static blob.  So 
>>>>>>>>>> maybe
>>>>>>>>>> the value of :body could be a string or a function of 1 arg, the 
>>>>>>>>>> route-- in
>>>>>>>>>> your code test with (fn?).
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> That's a good idea indeed. I've already thought about this for
>>>>>>>>> matching the request. I'd like this to work:
>>>>>>>>>
>>>>>>>>> {
>>>>>>>>>  (fn [request] (= (:path request) "/x"))
>>>>>>>>>   {:status 200 :content-type "application/json" :body (slurp
>>>>>>>>> (io/resource "my.json"))}
>>>>>>>>> {:path "/y" :query {:q (fn [q] (clojure.string/starts-with? q
>>>>>>>>> "some"))}}
>>>>>>>>>   {:status 200 :content-type "application/json" :body (slurp
>>>>>>>>> (io/resource "my2.json"))}
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> Thanks a lot for your help and feedback!
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> This gives you a single api, no macros, optional auto-server
>>>>>>>>>> start/stop or explicit server management.
>>>>>>>>>>
>>>>>>>>>> marc
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Tue, Mar 8, 2016 at 3:10 AM, Johan Haleby <johan....@gmail.com
>>>>>>>>>> > wrote:
>>>>>>>>>>
>>>>>>>>>>> Hi,
>>>>>>>>>>>
>>>>>>>>>>> I've just committed an embryo of an open source project
>>>>>>>>>>> <https://github.com/johanhaleby/fake-http> to fake http
>>>>>>>>>>> requests by starting an actual (programmable) HTTP server. 
>>>>>>>>>>> Currently the
>>>>>>>>>>> API looks like this (which in my eyes doesn't look very Clojure 
>>>>>>>>>>> idiomatic):
>>>>>>>>>>>
>>>>>>>>>>> (let [fake-server (fake-server/start!)
>>>>>>>>>>>         (fake-route! fake-server "/x" {:status 200 :content-type 
>>>>>>>>>>> "application/json" :body (slurp (io/resource "my.json"))})
>>>>>>>>>>>         (fake-route! fake-server {:path "/y" :query {:q 
>>>>>>>>>>> "something")}} {:status 200 :content-type "application/json" :body 
>>>>>>>>>>> (slurp (io/resource "my2.json"))})]
>>>>>>>>>>>         ; Do actual HTTP request
>>>>>>>>>>>          (shutdown! fake-server))
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> fake-server/start! starts the HTTP server on a free port (and
>>>>>>>>>>> thus have side-effects) then you add routes to it by using
>>>>>>>>>>> fake-route!. The first route just returns an HTTP response with
>>>>>>>>>>> status code 200 and content-type "application/json" and the 
>>>>>>>>>>> specified
>>>>>>>>>>> response body if a request is made with path "/x". The second line 
>>>>>>>>>>> also
>>>>>>>>>>> matches that a query parameter called "q" must be equal to 
>>>>>>>>>>> "something. In
>>>>>>>>>>> the end the server is stopped.
>>>>>>>>>>>
>>>>>>>>>>> I'm thinking of converting all of this into a macro that is used
>>>>>>>>>>> like this:
>>>>>>>>>>>
>>>>>>>>>>> (with-fake-routes!
>>>>>>>>>>> "/x" {:status 200 :content-type "application/json" :body (slurp
>>>>>>>>>>> (io/resource "my.json"))}
>>>>>>>>>>> {:path "/y" :query {:q "something")}} {:status 200 :content-type
>>>>>>>>>>> "application/json" :body (slurp (io/resource "my2.json"))})
>>>>>>>>>>>
>>>>>>>>>>> This looks better imho and it can automatically shutdown the
>>>>>>>>>>> webserver afterwards but there are some potential problems. First 
>>>>>>>>>>> of all,
>>>>>>>>>>> since starting a webserver is (relatively) slow it you might want 
>>>>>>>>>>> to do
>>>>>>>>>>> this once for a number of tests. I'm thinking that perhaps as an
>>>>>>>>>>> alternative (both options could be available) it could be possible 
>>>>>>>>>>> to first
>>>>>>>>>>> start the fake-server and then supply it to with-fake-routes! as
>>>>>>>>>>> an additional parameter. Something like this:
>>>>>>>>>>>
>>>>>>>>>>> (with-fake-routes!
>>>>>>>>>>>         fake-server ; We pass the fake-server as the first
>>>>>>>>>>> argument in order to have multiple tests sharing the same 
>>>>>>>>>>> fake-server
>>>>>>>>>>> "/x" {:status 200 :content-type "application/json" :body (slurp
>>>>>>>>>>> (io/resource "my.json"))}
>>>>>>>>>>>  {:path "/y" :query {:q "something")}} {:status 200
>>>>>>>>>>> :content-type "application/json" :body (slurp (io/resource 
>>>>>>>>>>> "my2.json"))})
>>>>>>>>>>>
>>>>>>>>>>> If so you would be responsible for shutting it down just as in
>>>>>>>>>>> the initial example.
>>>>>>>>>>>
>>>>>>>>>>> Another thing that concerns me a bit with the macro is that
>>>>>>>>>>> routes doesn't compose. For example you can't define the route 
>>>>>>>>>>> outside of
>>>>>>>>>>> the with-fake-routes! body and just supply it as an argument to
>>>>>>>>>>> the macro (or can you?). I.e. I think it would be quite nice to be 
>>>>>>>>>>> able to
>>>>>>>>>>> do something like this:
>>>>>>>>>>>
>>>>>>>>>>> (let [routes [["/x" {:status 200 :content-type
>>>>>>>>>>> "application/json" :body (slurp (io/resource "my.json"))}]
>>>>>>>>>>>               [{:path "/y" :query {:q "something")}} {:status
>>>>>>>>>>> 200 :content-type "application/json" :body (slurp (io/resource
>>>>>>>>>>> "my2.json"))}]]]
>>>>>>>>>>>      (with-fake-routes routes))
>>>>>>>>>>>
>>>>>>>>>>> Would this be a good idea? Would it make sense to have
>>>>>>>>>>> overloaded variants of the with-fake-routes! macro
>>>>>>>>>>> to accommodate this as well? Should it be a macro in the first 
>>>>>>>>>>> place? What
>>>>>>>>>>> do you think?
>>>>>>>>>>>
>>>>>>>>>>> Regards,
>>>>>>>>>>> /Johan
>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>>> You received this message because you are subscribed to the
>>>>>>>>>>> Google
>>>>>>>>>>> Groups "Clojure" group.
>>>>>>>>>>> To post to this group, send email to clo...@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+u...@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+u...@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 a topic in
>>>>>>>>> the Google Groups "Clojure" group.
>>>>>>>>> To unsubscribe from this topic, visit
>>>>>>>>> https://groups.google.com/d/topic/clojure/gieS5hQCUm4/unsubscribe.
>>>>>>>>> To unsubscribe from this group and all its topics, 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 a topic in
>>>>>>> the Google Groups "Clojure" group.
>>>>>>> To unsubscribe from this topic, visit
>>>>>>> https://groups.google.com/d/topic/clojure/gieS5hQCUm4/unsubscribe.
>>>>>>> To unsubscribe from this group and all its topics, 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 a topic in the
>>>>> Google Groups "Clojure" group.
>>>>> To unsubscribe from this topic, visit
>>>>> https://groups.google.com/d/topic/clojure/gieS5hQCUm4/unsubscribe.
>>>>> To unsubscribe from this group and all its topics, 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 a topic in the
>>> Google Groups "Clojure" group.
>>> To unsubscribe from this topic, visit
>>> https://groups.google.com/d/topic/clojure/gieS5hQCUm4/unsubscribe.
>>> To unsubscribe from this group and all its topics, 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 a topic in the
> Google Groups "Clojure" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/clojure/gieS5hQCUm4/unsubscribe.
> To unsubscribe from this group and all its topics, 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.

Reply via email to