Re: Python dataclass equivalent

2022-01-20 Thread James Reeves
ttp://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/a5718e8b-71a6-40d5-b1da-ca2cdb10a71en%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/clojure/a5718e8b-71a6-40d5-b1da-ca2cdb10a71en%40googlegroups.com?utm_medium=email_source=footer>.

-- 
James Reeves
booleanknot.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/da5de1bf-a466-4b78-898a-84d9b6217a53%40www.fastmail.com.


Re: Rationale of behavior when invoking composite data type as 0-arity function

2021-11-21 Thread James Reeves
On Sun, 21 Nov 2021, at 2:22 PM, dieter.v...@gmail.com wrote:
> repl> (mydata)
> ... (ArityException)...
> repl> ; instead i have to type eval
> 
> repl> ((eval mymap) :b)
>  -304538205
> 
> I know its only 4 letters and a space extra, but software composition is 
> supposed to avoid code duplication and perhaps the idea makes sense that 
> invoking a map without arguments evaluates it... Hence the question about the 
> choice made for the current behavior.

Evaluating a map is a fairly costly and uncommon use case. I don't believe I've 
ever had cause to eval an entire map, or if I have it can't have been more than 
a few times in the past 12 years of using Clojure. If I call a data structure 
with no arguments, it is most likely to be a mistake, so my expectation would 
be for the compiler or runtime to raise an error.

Syntax sugar is generally reserved for very common operations. Each piece of 
sugar that is introduced is something extra the reader needs to learn. 
Moreover, if they see (eval x) it is clear an evaluation is taking place; if 
they see (x), it is not obvious at all.

Not only is performing a lookup on a map a very common operation, treating a 
map as a function makes intuitive sense. A function is a mapping between two 
sets; a map is also a mapping between two sets. It's logical that they might 
share an interface.

-- 
James Reeves
booleanknot.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/2e63a6d5-0136-4026-8f50-3643cf153d74%40www.fastmail.com.


Re: clojure is supposed to be 'code is data' yet I can't add to the end of a list?

2021-07-19 Thread James Reeves
Don't get be wrong: Clojure can manipulate lists easily. You can append items 
to a list with (concat xs '(5)) or use syntax quoting `(~@xs 5). You just can't 
use conj specifically, as that function has a particular use case.

The problem with manipulating code is that code is complex. The same 
functionality can be written in many different ways, and it's hard to account 
for every possibility, so any abstraction that treats code as data tends to be 
either be leaky or very simple (or occasionally, very complex).

Clojure *can* treat code as data, but it's one of those tools that has a narrow 
use case. Clojure's philosophy more revolves around *replacing* code with pure 
data, where possible. Reading is safer and more predictable than evaluating, 
and evaluating within narrow constraints is often better than reaching for the 
more general purpose eval.

On Mon, 19 Jul 2021, at 2:00 PM, SideStep wrote:
> Thanks James, will for something like it I think. Still, would be nice if 
> code was manipulatable with ease - clojure style. Code-is-data such a 
> powerful idea. 
> 
> On Sunday, July 18, 2021 at 7:43:20 PM UTC+2 James Reeves wrote:
>> __
>> "Code is data" comes up in Clojure less than newcomers might expect. As a 
>> rule of thumb, it should be the last tool you reach for, as it's easier to 
>> work with data structures that have a simpler and more constrained syntax.
>> 
>> It's often hard to give good advice when context is lacking, but if you have 
>> a grid, and want to supply a sequence of instructions to modify it, and you 
>> want to inspect and manipulate those instructions, then I'd suggest 
>> something like:
>> 
>> (transform
>>  (grid 10 10)
>>  [[:toggle 2 3 4 5]
>>   [:off 2 3 4 5]
>>   [:on 2 3 4 5]])
>> 
>> On Sun, 18 Jul 2021, at 5:40 PM, SideStep wrote:
>>> Thanks Tania! The point I'm making is that list (data structure for 
>>> evaluatable data/code) is not easily manipulatable with code in clojure. So 
>>> much for 'code-is-data'... 
>>> Thanks for the suggestion.
>>> In regards to rethinking it: it is supposed to be commands coming-in that 
>>> sets parts of the grid with on/off/toggle... I want to append those 
>>> commands (code) as data to the representation of a grid and evaluate the 
>>> list of commands to get the final state of the grid.
>>> Trying to embrace this code-is-data thing here.
>>> On Saturday, July 17, 2021 at 9:21:29 PM UTC+2 tanya.m...@gmail.com wrote:
>>>> 
>>>> Hi,
>>>> 
>>>> conj <https://clojuredocs.org/clojure.core/conj> adds at the end of a 
>>>> vector, but at the beginning of a list. It is how it is implemented. I 
>>>> think this 
>>>> <https://stackoverflow.com/questions/5734435/put-an-element-to-the-tail-of-a-collection>
>>>>  and this 
>>>> <https://medium.com/@greg_63957/conj-cons-concat-oh-my-1398a2981eab> sums 
>>>> it up why.
>>>> 
>>>> You could achieve what you want by using concat 
>>>> <https://clojuredocs.org/clojure.core/concat> (note this returns a 
>>>> LazySeq):
>>>> `user=> (concat grid '((off 1 2 3 6)))
>>>> (-> (grid 10 10) (toggle 2 3 4 5) (off 2 3 4 5) (on 2 3 4 5) (off 1 2 3 
>>>> 6))`
>>>> Though I'm not exactly sure what is the end goal of this but I'd rethink 
>>>> the way it is done. 
>>>> 
>>>> 
>>>> 
>>>> 
>>>> On Sat, 17 Jul 2021 at 14:24, SideStep  wrote:
>>>>> 
>>>>>  <https://stackoverflow.com/posts/68420449/timeline>
>>>>> 
>>>>> I have a representation of a matrix in grid.clj file:
>>>>> 
>>>>> `(-> (grid 10 10)
>>>>> (toggle 2 3 4 5)
>>>>> (off 2 3 4 5)
>>>>> (on 2 3 4 5))
`
>>>>> 
>>>>> 
>>>>> It's a list of functionts, first one initializes a grid, others modify it.
>>>>> Clojures' 'code is data' supposed to make it easy for me to modify that 
>>>>> representation by adding an instrucion at the *end* of collection. List 
>>>>> is an ordered collection right? Order matters. How do I add an 
>>>>> instruction to the end of the list then?
>>>>> Something like this:
>>>>> 
>>>>> 
>>>>> `(def grid (read-string (slurp "grid.clj")))
>>>>> (conj grid '(off 1 2 3 6))
`
>>>>> Yet I can't add to the end of the list, wh

Re: Strange Vector failure

2021-07-18 Thread James Reeves
njunctive list of objects 
>>> which, when evaluated, return a boolean.  It is an attempt to use doseq to 
>>> walk along that list, evaluating each entry, and anding that result with  
>>> boolean atom. It fails. A sketch of the code is this - taken from the error 
>>> message:
>>> 
>>> inside (defn AndList...
>>> 
>>> (reify 
>>> ie4clj.api.Inferrable 
>>> (defn evalMembers 
>>> [members] 
>>> (defn result (atom true)) 
>>> (doseq [x members] 
>>> (result = (and result (eval x 
>>> (println (clojure.core/deref result)) 
>>> (result))) - *failed: vector? at: [:fn-tail :arity-1 :params] spec: 
>>> :clojure.core.specs.alpha/param-list*
>>> 
>>> It could be that my Java background is clouding my use of clojure. Any 
>>> comments will be appreciated.
>>> 
>>> Thanks
>>> Jack
>>> 
>>> 
>>> -- 
>>> 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 
>>> <mailto:clojure%2bunsubscr...@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/f67cfcd0-8e1e-4780-bc00-f6993979e7afn%40googlegroups.com
>>>  
>>> <https://groups.google.com/d/msgid/clojure/f67cfcd0-8e1e-4780-bc00-f6993979e7afn%40googlegroups.com?utm_medium=email_source=footer>.
>> 
>> 
>> -- 
>> 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 
>> <mailto:clojure%2bunsubscr...@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/CAMZDCY3BWybiXzgoYaKK958z%2BWqTKf0o_5p9fq-huwutco9onw%40mail.gmail.com
>>  
>> <https://groups.google.com/d/msgid/clojure/CAMZDCY3BWybiXzgoYaKK958z%2BWqTKf0o_5p9fq-huwutco9onw%40mail.gmail.com?utm_medium=email_source=footer>.
> 
> 
> -- 
> 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/CAH6s0fywhEidRkLx8DytqEs5wtXOaFtULCkBWgW%2BRVpmSfQvjg%40mail.gmail.com
>  
> <https://groups.google.com/d/msgid/clojure/CAH6s0fywhEidRkLx8DytqEs5wtXOaFtULCkBWgW%2BRVpmSfQvjg%40mail.gmail.com?utm_medium=email_source=footer>.

-- 
James Reeves
booleanknot.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/bf637bb0-ca4d-4e0e-be06-a0ecd62b3180%40www.fastmail.com.


Re: Strange Vector failure

2021-07-18 Thread James Reeves
You have a "defn" there by mistake.

On Sun, 18 Jul 2021, at 6:41 PM, Jack Park wrote:
> I have a class which treats a sequence as a conjunctive list of objects 
> which, when evaluated, return a boolean.  It is an attempt to use doseq to 
> walk along that list, evaluating each entry, and anding that result with  
> boolean atom. It fails. A sketch of the code is this - taken from the error 
> message:
> 
> inside (defn AndList...
> 
> (reify 
> ie4clj.api.Inferrable 
> (defn evalMembers 
> [members] 
> (defn result (atom true)) 
> (doseq [x members] 
> (result = (and result (eval x 
> (println (clojure.core/deref result)) 
> (result))) - *failed: vector? at: [:fn-tail :arity-1 :params] spec: 
> :clojure.core.specs.alpha/param-list*
> 
> It could be that my Java background is clouding my use of clojure. Any 
> comments will be appreciated.
> 
> Thanks
> Jack
> 
> 
> -- 
> 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/f67cfcd0-8e1e-4780-bc00-f6993979e7afn%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/clojure/f67cfcd0-8e1e-4780-bc00-f6993979e7afn%40googlegroups.com?utm_medium=email_source=footer>.

-- 
James Reeves
booleanknot.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/6d1e2896-0dc9-4ed3-bcaa-15c125506e3b%40www.fastmail.com.


Re: clojure is supposed to be 'code is data' yet I can't add to the end of a list?

2021-07-18 Thread James Reeves
"Code is data" comes up in Clojure less than newcomers might expect. As a rule 
of thumb, it should be the last tool you reach for, as it's easier to work with 
data structures that have a simpler and more constrained syntax.

It's often hard to give good advice when context is lacking, but if you have a 
grid, and want to supply a sequence of instructions to modify it, and you want 
to inspect and manipulate those instructions, then I'd suggest something like:

(transform
 (grid 10 10)
 [[:toggle 2 3 4 5]
  [:off 2 3 4 5]
  [:on 2 3 4 5]])

On Sun, 18 Jul 2021, at 5:40 PM, SideStep wrote:
> Thanks Tania! The point I'm making is that list (data structure for 
> evaluatable data/code) is not easily manipulatable with code in clojure. So 
> much for 'code-is-data'... 
> Thanks for the suggestion.
> In regards to rethinking it: it is supposed to be commands coming-in that 
> sets parts of the grid with on/off/toggle... I want to append those commands 
> (code) as data to the representation of a grid and evaluate the list of 
> commands to get the final state of the grid.
> Trying to embrace this code-is-data thing here.
> On Saturday, July 17, 2021 at 9:21:29 PM UTC+2 tanya.m...@gmail.com wrote:
>> 
>> Hi,
>> 
>> conj <https://clojuredocs.org/clojure.core/conj> adds at the end of a 
>> vector, but at the beginning of a list. It is how it is implemented. I think 
>> this 
>> <https://stackoverflow.com/questions/5734435/put-an-element-to-the-tail-of-a-collection>
>>  and this 
>> <https://medium.com/@greg_63957/conj-cons-concat-oh-my-1398a2981eab> sums it 
>> up why.
>> 
>> You could achieve what you want by using concat 
>> <https://clojuredocs.org/clojure.core/concat> (note this returns a LazySeq):
>> `user=> (concat grid '((off 1 2 3 6)))
>> (-> (grid 10 10) (toggle 2 3 4 5) (off 2 3 4 5) (on 2 3 4 5) (off 1 2 3 6))`
>> Though I'm not exactly sure what is the end goal of this but I'd rethink the 
>> way it is done. 
>> 
>> 
>> 
>> 
>> On Sat, 17 Jul 2021 at 14:24, SideStep  wrote:
>>> 
>>>  <https://stackoverflow.com/posts/68420449/timeline>
>>> 
>>> I have a representation of a matrix in grid.clj file:
>>> 
>>> `(-> (grid 10 10)
>>> (toggle 2 3 4 5)
>>> (off 2 3 4 5)
>>> (on 2 3 4 5))
`
>>> 
>>> It's a list of functionts, first one initializes a grid, others modify it.
>>> Clojures' 'code is data' supposed to make it easy for me to modify that 
>>> representation by adding an instrucion at the *end* of collection. List is 
>>> an ordered collection right? Order matters. How do I add an instruction to 
>>> the end of the list then?
>>> Something like this:
>>> 
>>> `(def grid (read-string (slurp "grid.clj")))
>>> (conj grid '(off 1 2 3 6))
`
>>> Yet I can't add to the end of the list, which is a data structure that is 
>>> evaluatable as code. How is it 'code as data' if I can't add to the end of 
>>> the ordered collection that is meant for code (as data)?
>>> 
>>> 
>>> 
>>> -- 
>>> 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.
>>> To view this discussion on the web visit 
>>> https://groups.google.com/d/msgid/clojure/efd72013-a85e-46e8-b9db-10dde1a8a235n%40googlegroups.com
>>>  
>>> <https://groups.google.com/d/msgid/clojure/efd72013-a85e-46e8-b9db-10dde1a8a235n%40googlegroups.com?utm_medium=email_source=footer>.
> 
> 
> -- 
> 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 

Re: [ANN] Important upcoming changes to Clojars

2021-03-01 Thread James Reeves
page (https://www.statuspage.io/) provides free hosting for 
> http://status.clojars.org/
> 
> -- 
> 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/4148ed43-a978-4c7f-b76f-0dc14ff7a581%40www.fastmail.com.
> 

-- 
James Reeves
booleanknot.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/f012e559-ebe8-41fa-886d-b0b4ea173ec6%40www.fastmail.com.


Re: clojure.edn/read isn't spec compliant

2020-10-20 Thread James Reeves
On Wednesday, 21 October 2020 at 00:42:32 UTC+1 EuAndreh wrote:

> But that doesn't apply to clojure.edn: it is code for a format with an 
> specification, and it goes against the specification.
>

Where in the specification does it say that the edn reader should throw 
exceptions on errors?

-- 
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/51bf5b5c-99b1-4c57-8969-b50a1bb1b5a2n%40googlegroups.com.


Re: Building klipse demands too much

2020-06-27 Thread James Reeves
I started it up on MacOS and also found that after only a few minutes,
there was a 4GB jar. This is clearly not correct, and a 110GB jar is
definitely not correct.

However, I don't see anything in the README about lein install being the
right way to install this. It looks like it's meant to be compiled into a
js file, rather than a local maven dependency.

On Sat, 27 Jun 2020 at 21:52, Rostislav Svoboda 
wrote:

> I'm trying to build klipse. I launched
> lein install
> more than 3.5 hours ago. It's still running and the
> target/klipse-7.9.7.jar is >110GB (gigabytes) large and increasing... :( Is
> that normal? Does anybody know what the space and time requirements are?
>
> I issued a ticket https://github.com/viebel/klipse/issues/371 already
> (sorry for duplicating) but I hope here I reach a larger audience and get
> the answer quicker - before my HDD breaks apart.
>
> Thanks
>
> --
> 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/CAEtmmez6_488LoQzw%2BZ327ANPOyG%3DrM4L%2Bs6du-hY3RSvD3rbA%40mail.gmail.com
> <https://groups.google.com/d/msgid/clojure/CAEtmmez6_488LoQzw%2BZ327ANPOyG%3DrM4L%2Bs6du-hY3RSvD3rbA%40mail.gmail.com?utm_medium=email_source=footer>
> .
>


-- 
James Reeves
booleanknot.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/CALg24jRxUXPC7nAso%3DDdYvjZffez9Jt717Akjqe23h%2Bhvs9-xA%40mail.gmail.com.


Re: first time without state - and I'm lost

2020-05-13 Thread James Reeves
On Wed, 13 May 2020 at 12:16, Matthew Downey 
wrote:

> The most similar thing you could do to your Java code would be keeping
> the token in an atom inside of a connection record.
>

As a quick note, if you don't need polymorphism, maps should be favoured
over records.

-- 
James Reeves
booleanknot.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/CALg24jTZhHw%3DCSVa69_8RfCWtjMEmNRrMBESQdPOUgv-woLK4A%40mail.gmail.com.


Re: COVID-19 related layoffs

2020-03-18 Thread James Reeves
I don't want to seem callous, but software development may be one of the
industries best equipped to weather COVID-19, as developers can often work
remotely. That's not to say we're unaffected of course; but other
professions, such as retail, entertainment, tourism or any sector that
requires people to be physically presence is likely going to be hit much
harder. While my thoughts are with everyone affected, my inclination would
be to prioritise support to healthcare workers, and then to the industries
that are hit hardest.

On Wed, 18 Mar 2020 at 18:20, Ag Ibragimov 
wrote:

> I'm seeing more and more messages from people who lost their jobs due to
> the virus. Can we please collectively brainstorm some ideas of how can we
> help each other? The crisis is at its beginning stage. It would only get
> worse. Only together we can get through it. Maybe we can use Clojurists
> Together funds to help our colleagues? Let's do something now!
>
> --
> 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/ff7de3a8-744a-4ac8-8ca7-697522fe2ecd%40googlegroups.com
> <https://groups.google.com/d/msgid/clojure/ff7de3a8-744a-4ac8-8ca7-697522fe2ecd%40googlegroups.com?utm_medium=email_source=footer>
> .
>


-- 
James Reeves
booleanknot.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/CALg24jS3GQVr4Ypb2q7RtXOhPw8hf%2BwHD0AZ9UrHk76s3P5fiQ%40mail.gmail.com.


Re: Bit rot and leiningen?

2020-02-04 Thread James Reeves
that because my code has not changed, the version of Clojure
> used has not changed, and the dependencies have not changed, the only thing
> which is not controlled for is Leiningen. Has anyone else seen a problem
> like this, and if so how did you cure it?
>
> --
> 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/4ce229bf-99c0-4922-aca2-8f0565e7feb0%40googlegroups.com
> <https://groups.google.com/d/msgid/clojure/4ce229bf-99c0-4922-aca2-8f0565e7feb0%40googlegroups.com?utm_medium=email_source=footer>
> .
>


-- 
James Reeves
booleanknot.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/CALg24jRV-2otS889cQ_Df-qwH6-%3Dy%2Bp2ZB1pKkZhN7sRx%2BRYnQ%40mail.gmail.com.


Re: Keys in EDN maps: keywords or symbols

2019-10-25 Thread James Reeves
As you point out, symbols in edn have no inherent meaning; it's entirely up
to how you interpret them. However, if you saw the symbol
"clojure.core/conj" in an edn file, then the chances are that it's intended
to refer to a Clojure function. Similarly, the symbol "PI" likely refers to
the mathematical constant.

A good litmus test is to replace the symbol with the thing it identifies,
and then see if the data still makes sense. So if we take your example:

{:angle PI}

We can substitute the symbol for the data it identifies:

{:angle 3.141592653589793}

And the edn file still makes sense. It's lost no significant semantic
meaning. However, if we return to your earlier example:

{username "vasya"}

What external identity does the symbol "username" have? If we say that it's
"vasya", then the substitution test fails:

{"vasya" "vasya"}

Since "username" has no meaning beyond itself, it should ideally be a
keyword:

{:username "vasya"}


On Fri, 25 Oct 2019 at 15:30, Anton Vodonosov  wrote:

> Thank you for responses.
>
> The last two arguments do not resolve the doubt, however:
>
> 1. symbols also implement IFn:
>
> (require 'clojure.edn)
> ('a (clojure.edn/read-string "{a 1 b 2}"))
> => 1
>
> 2. EDN does not specify any evaluation model, so how can a symbol
> designate something "in isolation"?
> For example, clojure.core/conj in the context of EDN does not
> designate a function - EDN is not Clojure.
>
>>
> One way I can imagine symbols to designate something is by agreement
> of particular EDN config file format.
> Maybe a user can specify {:angle PI}, and this specific config file
> format declares that the PI symbol
> can be used to refer the 3.14... constant.
>
> Still, I'm not sure such interpretation implies symbols in map keys
> should be resolved by the config file parser
> to some values
>
>
>
>
> --
> 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/68a3fce8-b63a-420b-9fbd-904f911a746b%40googlegroups.com
> <https://groups.google.com/d/msgid/clojure/68a3fce8-b63a-420b-9fbd-904f911a746b%40googlegroups.com?utm_medium=email_source=footer>
> .
>


-- 
James Reeves
booleanknot.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/CALg24jRx4vrEv8R7POX5XpT90BCpA57sxO-AeWrJnPV1oBARRQ%40mail.gmail.com.


Re: Keys in EDN maps: keywords or symbols

2019-10-24 Thread James Reeves
On Thu, 24 Oct 2019 at 16:48, Anton Vodonosov  wrote:

> Regarding the idea that a keyword is an identifier that designates itself,
> while a symbol is a keyword that designates something else.
>
> Keys in config file map do not designate themselves, they designate the
> corresponding map values.
>
> {username "vasya" email "a@b.c"}
>

Sure, but if I'm reading the edn spec correctly, the intention is that
symbols *in isolation* should identify something. So if I just wrote:

username

What does that identity? If it has no identity beyond itself, then it
should be a keyword. Contrast that to a symbol like:

clojure.core/conj

We know that symbol identifies a clojure function. Even outside of a map,
it has an external identity.

-- 
James Reeves
booleanknot.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/CALg24jTTnA7VXs-kyURLY%3DhzxPZX3jP%2BgMJ38mf1eLe_7AzESg%40mail.gmail.com.


Re: Keys in EDN maps: keywords or symbols

2019-10-24 Thread James Reeves
In edn, a keyword is an identifier that designates itself, while a symbol
is a keyword that designates something else.

This means keys in a map should generally be keywords, unless they identify
something beyond themselves. For example:

{:profiling/function-count {clojure.core/vec 10}}

On Thu, 24 Oct 2019 at 05:32, Anton Vodonosov  wrote:

> I'm working on a config file format in EDN, and in doubt: should I use
> keywords or symbols as map keys.
>
> After all, the colon is an extra keyboard press - an extra effort for
> users.
>
> As EDN parser doesn't evaluate expressions, there is no need to quote
> symbols when using them as EDN map keys (unlike clojure map literals)
>
> I mean,
>
> (edn/read-string "{a 1 b 2}")
>
> works, while using a clojure map literal would require quoting A and B:
>
> {'a 1 'b 2}
>
> So, is it a good idea to use symbols instead of keywords as map keys in a
> config file?
>
> Probably, an advantage of keywords that they look different visually, so a
> reader easily distinguishes keys from values; But proper indentation,
> optional commas between the key-value pairs in map may be enough for a
> reader to understand everything immediately.
>
>
> --
> 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/b4c1d021-a624-482b-9e75-fa5c08057a42%40googlegroups.com
> <https://groups.google.com/d/msgid/clojure/b4c1d021-a624-482b-9e75-fa5c08057a42%40googlegroups.com?utm_medium=email_source=footer>
> .
>


-- 
James Reeves
booleanknot.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/CALg24jRyjXXT%3DNarD2%3DFjNZXb_06tfCZwyAyFZAK%2BQWK3YtaiA%40mail.gmail.com.


Re: The magic of Lisps

2019-04-28 Thread James Reeves
Macros allow for experimentation in language design, not only by third
parties, but also by the developers of the language themselves. If you have
an idea for some new piece of syntax, it can be tried out in a library
first.

Macros are also useful for precompiling code for performance. If you have a
literal data structure you need to transform, or even one that's partially
literal, you can use macros to transform those parts at compile time.

That's not to say macros are written often; but they have an important
niche.

Regarding DSLs, I don't think applications are often written using an
encompassing internal DSL. I think most of the time when people talk about
a DSL, it's actually just an overly complex API.

In my view, a good DSL is both more consise within a domain, and less
powerful than a general purpose language. A regular expression, for
example, can concisely search through text, but has no side effects and is
guaranteed to halt at some point. Certain regex libraries even go further,
and guarantee they will halt within a time proportional to the input text.

Ideally we should be aiming for the *least* powerful tool for the job,
which often means using data to describe a solution rather than arbitrary
code. Not only is this more reliable, it's also more transparent and allows
for greater introspection.

For example, my own Integrant <https://github.com/weavejester/integrant>
library replaces the dependency management of an application with a data
structure. This is less powerful, because the dependencies need to be
explicitly mapped out beforehand, but it's also more reliable and allows
for introspection.

Going further, Cognitect's Vase <https://github.com/cognitect-labs/vase>
allows for micro-services to be expressed almost entirely through a data
structure.

Maybe these examples allow people to write applications faster, but I think
it's more important that they allow applications to be written more
reliably. Over time, applications that are reliable and predictable are
going to be easier for people to continue developing.

On Sun, 28 Apr 2019 at 05:46, Erik Assum  wrote:

> First of all, this might very well be a ramble without much sense, but
> please bear with me.
> Secondly, I’m writing this first and foremost not as an application
> programmer.
>
> Having programmed in the crud-application business some twenty years
> professionally, the last couple of them in Clojure, there are (at least)
> two things (that might be related) that puzzle me:
>
> 1) The power of macros
> I see, and acknowledge that eg the go-macro core.async is a wonderful
> piece of work, and that it’s really cool that it could be done in a
> library. But as an application programmer, I really don’t care if it’s a
> macro or a language feature, and I couldn’t really see myself investing
> that amount of time (nor would I have the skills to do so if I had the
> time) to solve my concurrency problems in such a general manner.
>
> 2) The creating of a DSL for your problem domain, and then write a custom
> compiler to solve your problem
> In my (most optimistic view) every program that I write is somewhat an
> internal DSL, built up of domain-specific functions, glued together with
> Clojure. But I don’t feel that this is very specific to how I program in
> Clojure vs other languages.
>
> So what I’d really like to achieve with this post is two things
>
> 1) Arguments ranging from  “Oh, you should look at it from this angle” to
> “That’s how I feel too” to “You’re totally wrong, because…”
>
> 2) Pointers to blogs/articles/codebases which shows how applications
> written either with extensive use of macros or by implementing an internal
> DSL (and compiler) are significantly quicker to develop than their
> brute-force alternatives.
>
> You might consider this as a first effort to create a presentation around
> the subject :)
>
> Erik.
>
> --
> 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.
>


-- 
James Reeves
booleanknot.com

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@goo

Re: Noob question on the --> macro implementation

2019-01-26 Thread James Reeves
I believe he's just saying it's simpler and possibly more efficient.

Unless I'm missing something subtle in the way this is resolved, I believe
Ujjwal is right that:

`(~(first form) ~@(next form) ~x)

Is equivalent to:

`(~@form ~x)

On Sat, 26 Jan 2019 at 19:04, Andy Fingerhut 
wrote:

> When you ask "am I right?" about your proposed change, what is it that the
> current behavior does not do, that your change would do?  Do you have some
> use case in mind that works with your change, but doesn't with the current
> implementation?
>
> Andy
>
> On Sat, Jan 26, 2019 at 10:50 AM Ujjwal Thaakar 
> wrote:
>
>> Hi,
>> I'm trying to learn Clojure and I just curiously typed
>> (source ->>)
>>  in the REPL and was wondering about this:
>> https://github.com/clojure/clojure/commit/749a0ad8b66c781d8176833f0ad26cfe6b9b24e3#r32075784
>>
>> Am I missing something?
>>
>> --
>> 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.
>


-- 
James Reeves
booleanknot.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.


Re: undocumented one-argument call of reducer

2019-01-25 Thread James Reeves
The 1-argument form of a reducing function is called at the end of the
reduce. So for example:

(defn mean
  "Transducer that returns the mean average."
  ([] [0 0])
  ([[sum count]]
   (/ sum count))
  ([[sum count] value]
   [(+ sum value) (inc count))


On Fri, 25 Jan 2019 at 22:19, Brian Craft  wrote:

> The transducers doc suggests transduce works with standard reducing
> functions, but then transduce makes a one-argument call to the function.
>
> The code docs for transduce say the reducing function must support a
> one-argument call, but don't give any information about what that call
> should do.
>
> It could be helpful to document this requirement, especially since the
> examples are all written with "+", which is rather misleading since it's
> not a standard reducing function with respect to its arity, and there is
> this unusual requirement on the arity of the function.
>
> --
> 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.
>


-- 
James Reeves
booleanknot.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.


Re: transducer parallelism

2019-01-25 Thread James Reeves
A transducer produces a reducing function, which processes in serial. You
can manually divide up the work into sections if you have some way of
combining the results at the end, however. I believe the
clojure.core.reducers namespace will work with any reducing function that
doesn't need a finalizer (e.g. 1-arity form), though you'll have to supply
your own combining function.

On Fri, 25 Jan 2019 at 22:19, Brian Craft  wrote:

> Are there any docs on transducer parallelism? I had the impression, from
> various sources, that they could operate in parallel, but in doing some
> benchmarks over a largish collection (counting character frequencies in
> 1.3M strings), transduce never uses more than one thread. Is this expected?
> If not, how would one debug it?
>
> --
> 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.
>


-- 
James Reeves
booleanknot.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.


Re: How should I debug a poorly performing small web app, using Jetty?

2019-01-19 Thread James Reeves
I'd first try increasing the connection pool size and see if that affects
things. That should tell you if the issue is an issue with blocked
connections.

On Sat, 19 Jan 2019 at 21:25,  wrote:

> I'm looking for advice about how to debug this.
>
> I wrote a small web app. It has about 1,200 lines of code. It is fairly
> standard for a Clojure app, it uses Jetty, and Compojure. It uses MongoDB.
>
> I'm just working on my MacBook Pro right now, so there is no issue such as
> using Nginx or load balancers.
>
> I can start the app up, and reach it on port 8082, and see all of the
> pages.
>
> However, this app does have a scheduled task that runs every 15 minutes
> and which is fairly demanding. It imports a large number of JSON files from
> an S3 bucket and stores them in MongoDB.
>
> This all works fine, but during the import, the app is no longer
> responsive on port 8082. The browser gets nothing back.
>
> My first thought was "I'm stupid because I've blocked the main thread,
> I've got too much going on." But then I thought "Wait, Jetty does not run
> on the main thread, so it shouldn't be effected by whatever I'm doing on
> the main thread."
>
> So now I'm thinking, I'm doing some database work on the main thread, and
> this keeps the Ring handlers from looking up information from the database,
> so there is perhaps some kind of timeout issue? Like, the handler tries to
> reach MongoDB, finds it unresponsive, and gives up after a certain amount
> of time? Or too many functions are sharing a single connection to MongoDB,
> so that is the problem.
>
> I'm testing, in part, by moving all of the database calls to background
> threads, and giving each separate connections to MongoDB, but I'm also
> looking for advice about other problems I should look for.
>
>
>
> --
> 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.
>


-- 
James Reeves
booleanknot.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.


Re: Any way to replace function body?

2019-01-19 Thread James Reeves
Yes, the alter-var-root function allows you to change a var's definition:

  (alter-var-root
   #'fetch-data
   (fn [original-fetch-data]
 (fn [& args]
   (let [result (apply original-fetch-data args)]
 (transform-result result))

On Sat, 19 Jan 2019 at 14:58, Janko Muzykant  wrote:

> Hi,
>
> Is there an way to replace body of existing (interned) function with own
> code still being able to call original fn?
> Suppose, I have a function:
>
> (defn fetch-data [arg1 arg2]
>   (db/fetch-data ...))
>
> I would like to intern a slightly modified version of this fn. Something
> like this:
>
> (defn fetch-data [& args]
>   (let [result (apply original-fetch-data args)]
> (transform-result result)))
>
> The problem I see is how to keep the reference to original fetch-data fn
> (here denoted by original-fetch-data),
> so it could be still called in a altered version of fetch-data function.
>
> Best,
> JM.
>
>
>
> --
> 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.
>


-- 
James Reeves
booleanknot.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.


Re: Custom vectors/maps and sequence functions

2019-01-15 Thread James Reeves
On Tue, 15 Jan 2019 at 13:58,  wrote:

> So - do I miss something either in my knowledge or in the Clojure's
> documentation/implementation and is there a meaningful way to apply
> Clojure's and not mine filter/map/take/drop/sort etc. functions on a Table
> and to get a Table back, without going the monads/own functions for
> everything route or should I take it for granted that I can implement some
> custom types, but no way to get them be fully transparent to Clojure?
>

You could write:

(into (empty coll) xform coll)

Assuming coll is some implementation of IPersistentCollection and where
xform is your transducer.

So for example:

(into (empty table) (comp (filter process?) (map process)) table)

-- 
James Reeves
booleanknot.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.


Re: What do Clojure developers use for recurring functions, other than at-at

2018-12-17 Thread James Reeves
I'd use an executor:

  (ns example.main
(:import [java.util.concurrent Executors TimeUnit]))

  (def scheduler
(Executors/newScheduledThreadPool 32))

  (defn fetch-files []
(println "Fetching files...))

  (defn -main []
(.scheduleAtFixedRate scheduler ^Runnable fetch-files 15 15
TimeUnit/MINUTES))

On Mon, 17 Dec 2018 at 20:14,  wrote:

> I'm coming back to Clojure development after a year away. This is a fast
> moving community and it is hard to keep up when one is not working on it
> full time. I'm dusting off some code I wrote 2 years ago, and trying to
> bring all the dependencies up to their current versions.
>
> I have a function that fetches files from an AWS S3 bucket, every 15
> minutes. I had previously used the at-at library for this:
>
> https://github.com/overtone/at-at
>
> But at-at has not been updated in 6 years, so I assume it is abandoned. I
> have two questions about this:
>
> 1.) how else do Clojure programmers usually call recurring functionality?
>
> 2.) I am ignorant about the JVM, so I'm afraid I have to ask, at a
> fundamental level, how does at-at work? I know that if a function calls
> itself recurringly, on the JVM, one eventually gets stackoverflow. So how
> does at-at make its magic work?
>
> --
> 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.
>


-- 
James Reeves
booleanknot.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.


Re: [ANN] Clojure 1.10 has been released!

2018-12-17 Thread James Reeves
My thanks to everyone involved. I'm looking forward to trying this out.

On Mon, 17 Dec 2018 at 17:30, Alex Miller 
wrote:

> Clojure 1.10 focuses on two major areas: improved error reporting and Java
> compatibility.
>
>
> Error reporting at the REPL now categorizes
> <https://clojure.org/reference/repl_and_main#_error_printing> errors
> based on their phase of execution (read, macroexpand, compile, etc). Errors
> carry additional information about location and context as data, and
> present phase-specific error messages with better location reporting. This
> functionality is built into the clojure.main REPL, but the functionality is
> also available to other REPLs and tools with the ability to use and/or
> modify the data to produce better error messages.
>
>
> Clojure 1.10 now requires Java 8 or above and has been updated
> particularly for compatibility with Java 8 and Java 11. Changes included
> bytecode-related bug fixes, removed use of deprecated APIs, and updates
> related to the module system introduced in Java 9.
>
>
> See the change log
> <https://github.com/clojure/clojure/blob/master/changes.md#changes-to-clojure-in-version-110>
> for a complete list of all fixes, enhancements, and new features in Clojure
> 1.10.
>
>
> Thanks to all of the community members who contributed patches to Clojure
> 1.10 (first time contributors in bold):
>
>
>-
> *Alexander Kiel *
>- *Ben Bader*
>- Bruce Adams
>- *Cezary Kosko*
>- Erik Assum
>- *Eugene Kostenko*
>- Ghadi Shayban
>- *Gijs Stuurman*
>- Jozef Wagner
>-
> *Kwang Yul Seo *
>- *Matthew Gilliard*
>- Michał Marczyk
>- Nicola Mometto
>- Nikita Prokopov
>-
> *Sean Corfield *
>- *Sebastien Martel*
>- Shogo Ohta
>- Stuart Sierra
>
> --
> 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.
>


-- 
James Reeves
booleanknot.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.


Re: What's the end goal for tools.deps?

2018-11-04 Thread James Reeves
On Sun, 4 Nov 2018 at 18:58, Didier  wrote:

> I guess I see the need for a dependency manager. And I love having a CLI
> to launch Clojure programs. And I understand it is fundamental. That said,
> it always felt like Lein had solved that problem long ago. Maybe it wasn't
> official enough. But Lein could have been bundled with Clojure and
> effectively solved the same problems and more.
>

My impression is that the core devs prefer an approach made up of many
small, simple tools, rather than the batteries-included approach of
Leiningen. I don't think it's a case of Leiningen not being "official", but
that it's design isn't quite in the direction the core devs want to head
toward.

-- 
James Reeves
booleanknot.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.


Re: Mail queue thread

2018-10-27 Thread James Reeves
If I was building a system like the one you describe for real, then the
first tool I'd reach for would be a email sending service, like Mailgun,
Sendgrid, or AWS SES. These sorts of services take care of queuing mail,
retrying on failure, and keeping track of mail bounces. They also all have
free tiers: Mailgun is free for the first 10,000 emails per month, Sendgrid
is free for around 3,000 emails a month, and SES is free for 62,000 emails
per month. They also save me the trouble of maintaining and configuring my
own email sending system.

If I was building something myself, for whatever reason, then I'd make it
as simple as possible.

(defn send-queued-mail [db mail]
  (let [sent-successfully? (send-mail mail)]
(if sent-succesfully?
  (remove-mail-from-queue db mail

(defn send-queued-mail [db]
  (doseq [mail (fetch-queued-mail-in-priority-order db)]
(send-queued-mail db mail)))

(defn init-scheduler [db]
  (doto (Executors/newScheduledThreadPool 32)
(.scheduleAtFixedRate #(send-queued-mail db) 30 30 TimeUnit/SECONDS)))

I wouldn't have an application-specific queue, as I'd want it to be robust
against the process ending.

But I don't think there's any situation where I'd want to do it myself if I
could avoid it, not when there are solutions out there that already do all
of the heavy lifting for me.


On Sat, 27 Oct 2018 at 12:59,  wrote:

> Thanks for pointing out the submit function and explaining the wrapper.
>>> Would you specifically advise against sending the result back through a
>>> channel?
>>>
>>
>> It depends what you're trying to do. What are you doing with the result,
>> and what's your reasoning for not handling it in your "send-email!"
>> function?
>>
>
> That is a very good question. I currently believe that the there will be
> three different scenarios of sending emails.
>
> 1. Fire and (almost) forget - where delivery is not guaranteed but the app
> user will be notified if delivery was unsuccessful as soon as that status
> is available.
> 2. First send of a guaranteed delivery message - where all messages are
> stored in the DB but the send is attempted immediately.
> 3. Retry of sending a guaranteed delivery message - i.e., a failed send is
> picked up from the DB by some scheduled task.
>
> I would like the send-mail function to be agnostic of which of these
> scenarios a particular message is sent in (and not have to include any DB
> logic). Rather, it would just return the status whenever it's available and
> let the caller decide what to do with it (scenario 1 or 2). If the status
> is returned as a future, the caller would have wait until the future is
> realized to avoid blocking - and do this wait in a non-blocking manner. It
> seems that returning using a channel and receiving the status in a go block
> would achieve precisely this with very little code. Also, if there is a
> chain of function between the sender and the worker thread, the channel
> would bypass the caller chain and each chained caller doesn't need know the
> nature of the status. Also, if some reason there are multiple parties who
> are interested in the status (no use case yet), it would be easy to just
> add more return channels to the email. Does this also seem over-enginereed
> compared to just returning the future from the worker and letting it bubble
> up to however is interested?
>
> Thanks,
> Brjánn
>
>
>>
>> --
>> James Reeves
>> booleanknot.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 receiv

Re: Mail queue thread

2018-10-26 Thread James Reeves
On Fri, 26 Oct 2018 at 14:05,  wrote:

> Thanks for pointing out the submit function and explaining the wrapper.
> Would you specifically advise against sending the result back through a
> channel?
>

It depends what you're trying to do. What are you doing with the result,
and what's your reasoning for not handling it in your "send-email!"
function?

-- 
James Reeves
booleanknot.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.


Re: Mail queue thread

2018-10-25 Thread James Reeves
On Thu, 25 Oct 2018 at 21:47,  wrote:

> It seems that I somewhat over-engineered my queue :-) I don't know any
> Java so this is very helpful!
>

When it comes to Java concurrency, ExecutorService and BlockingQueue cover
a lot of bases.


> If I want to know the result of the email send within the worker
> thread, would you recommend sending it back through a channel?
>

You can actually get back a return value directly, though it requires a
wrapper function:

(defn submit [^java.util.concurrent.ExecutorService executor, ^Callable f]
  (.submit executor f))

(let [executor (java.util.concurrent.Executors/newFixedThreadPool 32)]
  result   (submit executor #(+ 1 1))]
  (prn @result))

In the above example we're using ".submit" rather than ".execute", which
tells the executor we care about the return value from the function and
want it back. It returns it as a future, result, which we can deref as
@result. When a future is dereferenced in Clojure, the current threat
blocks until it's receives a value.

The purpose of the "submit" function is to force the executor through type
hints to treat the function as a Callable with a return value. I wasn't
able to get it working without this wrapper.

One purpose of my queue was to be able to put urgent messages at the front
> of the queue. I guess that using a threadpool with workers does not give me
> any guarantee that the email is delivered immediately, since X emails may
> already have been added but not yet sent. I guess that one one use a
> dedicated thread(pool) for urgent messages?
>

Yes, you could do that. You could also use a priority queue with the
PriorityBlockingQueue class. A priority queue is a queue with a comparator
that allows you to control ordering, shunting certain items to the front.

There's a library called Claypoole
<https://github.com/TheClimateCorporation/claypoole> that packages all
these Java classes into nice Clojure functions, and it includes a priority
queue so I'd advise looking into it. I haven't tried it myself, but it
looks like you can do something like:

(require '[com.climate.claypoole :as cp])

(let [pool(cp/priority-threadpool 32)
  result1 (cp/future (cp/with-priority pool 1000) (send-email
important-mail))
  result2 (cp/future (cp/with-priority pool 0)(send-email
unimportant-mail))]
  (prn @result1)
  (prn @result2))

Which is probably easier than messing around with the executor classes
directly.

-- 
James Reeves
booleanknot.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.


Re: Mail queue thread

2018-10-25 Thread James Reeves
On Thu, 25 Oct 2018 at 19:01,  wrote:

> Thank you for the thorough explanation! So if I understand you correctly,
> if no calls are made to the executor thread, it will just rest silently
> until queue-email is called again - not consuming any server resources.
>

That's essentially correct.

Threads do take up a small amount of memory even when idle (IIRC its around
1M per thread), but unless you're dealing with thousands of threads or
you're dealing with very constrained memory, this can be ignored. Creating
a thread is relatively expensive, which is why they're often kept around
for reuse in thread pools.


> Are there any recommendations for the number of worker threads when each
> does IO?
>

It depends entirely on the external service you're communicating with. My
advice would be to choose a relatively small default, say 32 or under, and
then make it configurable from an environment variable or system property.
That way you can tune the service without changing the code.

(def mail-pool-size
  (Integer/parseInt (or (System/getenv "MAIL_POOL_SIZE") "32")))

-- 
James Reeves
booleanknot.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.


Re: Mail queue thread

2018-10-25 Thread James Reeves
The Java executor classes are essentially a queue backed by a thread pool
of workers.

So suppose we create a new executor:

(def executor
  (java.util.concurrent.Executors/newFixedThreadPool 32))

This creates an ExecutorService object with a pool of 32 worker threads. We
can pass it a zero-argument function to execute:

(.execute executor (fn [] (prn "Hello World")))

This function is placed on a queue until one of the 32 worker threads is
available to process it. In this case the function prints a message, but
you could write something to send an email instead:

(defn queue-email [email]
  (.execute executor (fn [] (send-email email)))

If we execute "queue-email" 10,000 times, then 10,000 "send-email" jobs
will be passed to the executor. The executor will pass them onto its 32
workers, effectively processing 32 at a time until it exhausts the queue.

If you want fewer emails to be sent at once, you can reduce the worker
thread pool size. In my earlier example, I used an executor with only one
worker thread.

On Thu, 25 Oct 2018 at 18:17,  wrote:

> Hi James,
>
> Thanks! How would one create a thread that continuously monitors a mail
> queue and sends any mails in it? Or do you mean that I would create one
> thread per mail that I want to send? Wouldn't that create a problem if I'm
> about to send 1 mails in one go?
>
> And thanks for the heads up regarding indefinite blocking - I'll make sure
> to guard against that.
>
> Thanks,
> Brjánn
>
> On Thu, 25 Oct 2018 at 18:57, James Reeves  wrote:
>
>> Hi Brjánn,
>>
>> Executing queued jobs in a background thread is a common task, and as it
>> happens there's a set of Java classes to do just that.
>>
>> (let [e (java.util.concurrent.Executors/newSingleThreadExecutor)]
>>   (.execute e #(prn "foo"))
>>   (.execute e #(prn "bar"))
>>   (Thread/sleep 1000)
>>   (.execute e #(prn "baz")))
>>
>> Don't worry about cleaning up a single thread. An inactive thread takes
>> up a minimal amount of VM memory and no CPU. You're going to use up more OS
>> resources deleting and recreating the thread.
>>
>> You do need to be careful that sending an email doesn't block
>> indefinitely, but usually I/O operations come with timeouts. Just ensure
>> you set a reasonable timeout and do something sensible when you can't send.
>>
>> On Thu, 25 Oct 2018 at 16:46,  wrote:
>>
>>> Hi,
>>>
>>> First, I would like to briefly present myself to the list. I'm a
>>> psychologist and researcher at the Karolinska Institutet in Stockholm,
>>> Sweden. I do research within the field of internet-based psychological
>>> treatment - which is a field that has grown a lot during the last 10-15
>>> years. I have developed my own web platform to deliver these treatments to
>>> patients with different mental and medical conditions. I wrote the first
>>> version in PHP, and not being a professional programmer, the code base is a
>>> big mess after > 10 years of development.
>>>
>>> Two years ago, a friend introduced me to Clojure. I had never worked
>>> with a lisp before, but I quickly fell completely in love with it. So many
>>> of the issues of programming in PHP completely disappeared! Words cannot
>>> express my gratitude to Rich for inventing Clojure, the core team, all
>>> developers out there who write extremely useful libraries, and my friend
>>> for introducing Clojure to me.
>>>
>>> I decided to completely rewrite my web platform in Clojure. I've chosen
>>> to do a gradual move from PHP to Clojure, meaning that I replace PHP code
>>> with Clojure code component by component and continuously test in
>>> production. Like I said, I'm not a professional programmer, and this
>>> venture poses a lot of challenges. I try to read everything I find in books
>>> and on the web, but when it comes to more complex issues, such as threads
>>> and async programming, I feel that I end up almost guessing and with a lot
>>> of trial and error. I have no idea how cautious one should be when
>>> launching a new thread (while it completely occupy the server???) and am
>>> often surprised when my go blocks suddenly freeze. I feel that I am at the
>>> mercy of the Clojure community if I want to understand these (and many
>>> other!) issues.
>>>
>>> This leads me to the subject of this email. I've decided to migrate my
>>> mail queue from PHP to Clojure. In PHP, it's just a cron job that executes
>>> every five minutes to send all emails (and actually also SMS-messages, but
&g

Re: Keyword namespacing best practices

2018-10-01 Thread James Reeves
I'd prefer an option map over kwargs in general, and I wouldn't namespace
the options because they're not something that I'd expect to stick around.

(fetch url {:timeout 10})

Regarding the output, if it's a Ring response map, I'd be inclined to leave
the keywords bare for compatibility. If it's not, then namespaced keywords
become more tempting to me, so long as the namespace can be aliased for
brevity:

(api/fetch url {:timeout 10})
=> #::api{:status 200, :body ""}

On Mon, 1 Oct 2018 at 02:45, Michael Gardner  wrote:

> I'm looking for some feedback on keyword namespacing. Say you're writing
> an API to be used by external clients that works something like this:
>
> (fetch url :timeout 10)
> => {:status 200, :body "..."}
>
> Would you namespace the :status and :body keywords in the response? What
> about the :timeout kwarg in the function call? Why or why not?
>
> --
> 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.
>


-- 
James Reeves
booleanknot.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.


Re: Clojure(Script) web apps in 2018

2018-09-24 Thread James Reeves
, open questions, but I'm hoping for
>>>> advice for the working programmer : )
>>>>
>>>> Of particular interest would be whether people feel any of the more
>>>> ambitious libraries (e.g. Replikative) are worth relying on for a serious
>>>> project, or are people generally still rolling their own, RPC style.
>>>>
>>>> Thanks very much, in advance!
>>>>
>>>> Tom
>>>>
>>>> --
>>>> 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.
>>>
>> --
>> - sent from my mobile
>>
>> --
>> 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.
>


-- 
James Reeves
booleanknot.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.


Re: How to escape a space in a keyword?

2018-08-09 Thread James Reeves
If Clojure lacks a type that exactly matches ION's symbol type, why not add
your own type with a record, then add a data reader for it.

For example: #ion/symbol "foo"

On Thu, 9 Aug 2018, 05:48 Didier,  wrote:

> Thanks Andy, ya I actually realized this, I'm using a custom reader
> literal now instead.
>
> > Why are you fighting so hard to make keywords with spaces? If you need
> things with spaces, use strings.
>
> Why have keywords at all then? What does a space add that somehow negates
> the premise of keywords?
>
> I see keywords over strings give you interning, namespaces, and the
> semantic that this value serves as an identifier. What's wrong with having
> that and a space as well?
>
> Also, to be more specific to my use case. If I convert ION symbols to
> Clojure strings, I've lost information, and can no longer convert back to
> the same ION.
>
> I need to do ION -> EDN -> ION in a lossless way. Piggybacking on keywords
> seemed easiest.
>
> --
> 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: Using dynamically loaded namespaces like plug-ins

2018-07-29 Thread James Reeves
You could write it like this:

(defn scenario-improve []
  (let [ns (str "aigympoc." aigympoc.config/scenario)]
(eval (read-string (str "(do (require '" ns ") (" ns "/improve)")

So we require, then run the function. However, we don't need to use eval
here if we require the namespace and find the var directly:

(defn scenario-improve []
  (let [ns (symbol (str "aigympoc." aigympoc.config/scenario))]
(require ns)
(let [improve (find-var (symbol ns "improve"))]
  (improve

On Sun, 29 Jul 2018 at 18:50, 'Daniel de Oliveira' via Clojure <
clojure@googlegroups.com> wrote:

> Hi there,
>
> I wanted to use dynamic loading of namespaces to achieve sort of a plugin
> structure but got kind of struck.
>
> I have a leiningen project, with the following files:
>
> -- src/aigympoc/config.clj
>
> (ns aigympoc.config)
>
> (def scenario "aigympoc.scenario1")
>
>
> - src/aigympoc/scenario1.clj
>
> (ns aigympoc.scenario1)
>
> (defn improve [] ...)
> (defn success? [] ...)
>
>
> - src/aigympoc/scenario2.clj
>
> (ns aigympoc.scenario2)
>
> (defn improve [] ...)
> (defn success? [] ...)
>
>
> - src/aigympoc/gameloop.clj
>
>
> (ns aigympoc.gameloop
>   (:require
> aigympoc.config
> ...
> aigympoc.scenario1; <-- how to get
> aigympoc.scenario2))) ; <-- rid of these
>
> ...
>
>
> (defn step
>
>   []
>
>...
>   (do
> (if (= (scenario-success?) \t)
>   (prn "success")
>   (do (scenario-improve)
>
>
> (defn scenario-improve
>   []
>   (eval (read-string (str "(aigympoc." aigympoc.config/scenario 
> "/improve)"
>
>
> (defn scenario-success?
>   []
>   (eval (read-string (str "(aigympoc." aigympoc.config/scenario 
> "/success?)"
>
>
> I would really like to get rid of the requires to aigympoc.scenario1 and 
> aigympoc.scenario1,
>
> so that scenarios can get loaded on the fly, by just putting a new file to a 
> folder and setting the name in the config (or giving it on runtime).
>
> I spent quite some time on it, but cannot figure it out.
>
>
> I'm really new to clojure so I think I may be trying to use it
> non-idiomatically and there are better ways for doing it.
> In any case I would be happy if someone more experienced could point me in
> the right direction.
>
>
>
>
> --
> 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.
>


-- 
James Reeves
booleanknot.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.


Re: OK idea to replace conj and cons with "prepend" and "append" macros that have consistent behavior and return same types as args?

2018-07-22 Thread James Reeves
On Sun, 22 Jul 2018 at 22:22, Christian Seberino 
wrote:

> - conj adds an element in the place best for the collection type.
>
>
> Is this a valid hypothetical to worry about?...
>
> Imagine you're the teacher and make the comment above.
>
> Student responds..
>
> "But why, Mr. Teacher, is the 'best' place different for lists and
> vectors?  That seems strange that they are opposite."
>

You can either explain, or say: "For now, accept that they are."

I don't think this is hard. You can choose to discuss it or not, but all
learning has boundaries. There's a well-known interview
<https://fs.blog/2012/01/richard-feynman-on-why-questions/> where Richard
Feynman goes into the limits of asking "why?".

Also if you introduce a function like "comb", a student may very well ask
you why there are lists and vectors when they behave in the same way. Then
you'd have the same problem, except worse, as you'd also need to explain
that "comb" is just a crutch that shouldn't be used outside of the
classroom.

-- 
James Reeves
booleanknot.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.


Re: How define alias for .indexOf? (def somealias .indexOf) does not work.

2018-07-19 Thread James Reeves
You'd need to wrap it in a function, like:

(defn index-of [^String haystack ^String needle]
  (.indexOf haystack needle))

On Thu, 19 Jul 2018 at 18:33, Christian Seberino 
wrote:

> How define alias for .indexOf?
>
>  (def somealias .indexOf) does not work.
>
> cs
>
> --
> 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.
>


-- 
James Reeves
booleanknot.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.


Re: OK idea to replace conj and cons with "prepend" and "append" macros that have consistent behavior and return same types as args?

2018-07-18 Thread James Reeves
On Wed, 18 Jul 2018 at 20:40, Gregg Reynolds  wrote:

>
> On Wed, Jul 18, 2018, 2:25 PM Robert Levy  wrote:
>
>> Literals can be persisted to strings and read back in with no problem,
>> whereas non-literals can't.
>>
>
> That's a different definition of "literal", no? James talked about
> evaluation, not printed form. Value != Print representation?
>

In practical terms there's no real distinction. All data literals in
Clojure can be printed.

-- 
James Reeves
booleanknot.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.


Re: OK idea to replace conj and cons with "prepend" and "append" macros that have consistent behavior and return same types as args?

2018-07-18 Thread James Reeves
On Wed, 18 Jul 2018 at 20:19, Gregg Reynolds  wrote:

>
> On Wed, Jul 18, 2018, 1:55 PM James Reeves  wrote:
>
>>
>> Function expressions don't evaluate to themselves.
>>
>
> To me that means either the definition is wrong or your literal? is
> rigged. Probably the latter; "literal" is meta, it can't be in the language.
>

How can it be rigged? It's a one line function that just returns true if an
expression evaluates to itself.

You can run read-string directly and see that reading a function expression
results in a seq:

user=> (read-string "#(%)")
(fn* [p1__175#] (p1__175#))
user=> (seq? *1)
true

It doesn't become a function until it's evaluated

Look at it this way: the meaning ("value") of "lambda x.x+1" is just the
> function that increments its arg. Of course you have to "evaluate" to know
> that, but you also have to evaluate "2" in the same way to know what it
> means.
>

Clojure (and lisps in general) distinguish between reading data and
evaluating it. The integer expression "2" does not need to be evaluated:

user=> (read-string "2")
2
user=> (int? 2)
true

And evaluating it only returns itself:

user=> (eval 2)
2
user=> (= 2 (eval 2))
true

In Clojure terminology, you don't need to evaluate "2" to know what it
means. However, you do need to evaluate an expression like (fn [x] (+ x
1)). Merely reading it returns a list.

Anyway my point is that clojure, like lisp, is a form of the lambda
> calculus, where everything is a function, even the Nats like 2. To me at
> least that is one of the most important lessons of functional programming.
> Ymmv.
>

It isn't.

Certainly Clojure can trace some of its lineage back to the lambda
calculus, but that's all. Not everything in Clojure is a function, or even
resembles a function.

-- 
James Reeves
booleanknot.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.


Re: OK idea to replace conj and cons with "prepend" and "append" macros that have consistent behavior and return same types as args?

2018-07-18 Thread James Reeves
On Wed, 18 Jul 2018 at 19:38, Gregg Reynolds  wrote:

>
> On Tue, Jul 17, 2018, 4:11 PM James Reeves  wrote:
>
>>
>> A data literal evaluates to itself. So for example, `2` is a literal,
>> because we only need to read it to know its value, whereas `(+ 1 1)`
>> isn't a literal, because we also need to evaluate it to work out the value.
>>
>
> Fair enough. But by that definition function expressions are also literals.
>

Not at all:

user=> (defn literal? [s] (let [e (read-string s)] (= e (eval e
#'user/literal?
user=> (literal? "2")
true
user=> (literal? "(fn [x] x)")
false
user=> (literal? "#(%)")
false
user=> (literal? "+")
false

Function expressions don't evaluate to themselves.

-- 
James Reeves
booleanknot.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.


Re: OK idea to replace conj and cons with "prepend" and "append" macros that have consistent behavior and return same types as args?

2018-07-17 Thread James Reeves
On Tue, 17 Jul 2018 at 22:47, Christian Seberino 
wrote:

> When writing software in Clojure, the data structures are often the
>> keystone of the codebase. When I write Clojure, I start by mapping out what
>> data structures and keywords I need, and from there write functions around
>> them. It's for this reason that I don't think prepend and append functions
>> are particularly useful for students, as the teacher should be encouraging
>> them to think *more* about the data structures they're using, not less.
>>
>
> I presume you mean that thinking more about data structures and thinking
> about computational efficiency are inseparable?  You can't do the former
> without the latter?
>

Efficiency follows in the wake of intent. For example, if you intend a
collection to be unordered and unique, you could use a set. A set happens
to also be efficient at checking whether an item is contained within it,
but this efficiency follows from how the data is intended to be used.

-- 
James Reeves
booleanknot.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.


Re: OK idea to replace conj and cons with "prepend" and "append" macros that have consistent behavior and return same types as args?

2018-07-17 Thread James Reeves
On Tue, 17 Jul 2018 at 21:06, Christian Seberino 
wrote:

>
> Clojure, on the other hand, takes great care to ensure that its data can
>> always be represented as literals. For data that isn't a standard
>> collection type, there are tagged literals. Clojure syntax starts from a
>> representation of data, and in order to really understand it, I think it
>> needs to be taught from this principle as well
>>
>
> Can you elaborate?  I really want to get your point but I'm not so
> proficient with the lingo.  What do you mean by a "literal" and "tagged
> literals"?
>

A data literal evaluates to itself. So for example, `2` is a literal,
because we only need to read it to know its value, whereas `(+ 1 1)` isn't
a literal, because we also need to evaluate it to work out the value.

A tagged literal is a literal preceded by a tag. For example, `#inst
"2018-07-17T20:45:59.766-00:00"` is a literal string preceded by the tag, `
#inst`, which denotes that the string holds a datetime.

And how is a focus on the representation of data different than Python
> beyond Python's less elegant grammar?
>

Clojure is unusual in that it dedicates the vast majority of its syntax to
describing data structures. When other languages introduce new syntax, it's
often syntax that improves how code is represented, rather than literal
data.

Other lisps have syntax revolving around data structures as well, of
course, but they tend to prioritise minimalism, whereas Clojure seeks - in
my view - to better describe data without stooping to evaluation.
Traditionally lisps have rejected any collection literals beyond lists,
whereas Clojure extends that to maps, sets and vectors.

When writing software in Clojure, the data structures are often the
keystone of the codebase. When I write Clojure, I start by mapping out what
data structures and keywords I need, and from there write functions around
them. It's for this reason that I don't think prepend and append functions
are particularly useful for students, as the teacher should be encouraging
them to think *more* about the data structures they're using, not less.

-- 
James Reeves
booleanknot.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.


Re: OK idea to replace conj and cons with "prepend" and "append" macros that have consistent behavior and return same types as args?

2018-07-17 Thread James Reeves
On Tue, 17 Jul 2018 at 19:52, Christian Seberino 
wrote:

> By the time a Clojure beginner is doing the kind of hardcore concurrent
> applications that Clojure is great at, he/she will know how to use a
> profiler.  At the point,  they'll be ready (and motivated!) to learn about
> the nuances of conj and friends.
>

I think this is approaching Clojure from the wrong direction. If I was
teaching Clojure, I'd build the lessons around the data structures first.

My opinion is that many languages take a "code first" approach to language
design, whereas Clojure takes a "data first" approach, and this affects how
it should best be taught.

For example, in Python you can write {1, 2} to produce a set, or {1: 2} to
produce a dict. But what does {} produce? Is it an empty set, or an empty
dict? Python chooses the latter, leaving the literal syntax for sets
incomplete. To my mind this is indicative of a design approach that sees
literal data syntax as sugar for data constructors, and not something that
deserves first class consideration.

Clojure, on the other hand, takes great care to ensure that its data can
always be represented as literals. For data that isn't a standard
collection type, there are tagged literals. Clojure syntax starts from a
representation of data, and in order to really understand it, I think it
needs to be taught from this principle as well.

-- 
James Reeves
booleanknot.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.


Re: Spaces between brackets?

2018-06-22 Thread James Reeves
At least in edn they're not necessary:

The delimiters { } ( ) [ ] need not be separated from adjacent elements by
> whitespace.
>

I'd argue that it's more consistent to treat all elements the same,
however, be they collection, keyword, symbol or whatever else.

On Sat, 23 Jun 2018 at 00:34, Didier  wrote:

> Hi,
>
> I've noticed that it seems you can omit the space between brackets, and
> everything still parses as normal. I tend to prefer doing that in some
> instances, for example:
>
> (fn[a b] (+ a b))
>
> It seems to hold in all scenarios, for example:
>
> [1 '...[2 3]]
>
> Yields [1 '... [2 3]]
>
> And
>
> [1[2[3]]]
>
>
> Yields [1 [2 [3]]]
>
> Or
>
> (defn add[a b] (+ a b))
>
> Etc.
>
> So my question is: *Is this an official parse rule for Clojure and its
> dialects like ClojureScript, ClojureCRL and EDN, or the fact this works is
> accidental, and shouldn't be relied on?*
>
> --
> 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.
>


-- 
James Reeves
booleanknot.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.


Re: Clojure Group

2018-04-16 Thread James Reeves
On 16 April 2018 at 17:36, Bijay Paudel <javabi...@gmail.com> wrote:

> I post lots of questions but I did not get any response
>

Are you sure they're getting through? I just did a search for your email
address in the Clojure group and got this thread as the only result.

-- 
James Reeves
booleanknot.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.


Re: Clojure Games

2018-04-16 Thread James Reeves
Go ahead. Asking questions about Clojure is definitely under this group's
remit :)

On 16 April 2018 at 09:56, Peter Ashford <peter.m.ashf...@gmail.com> wrote:

> Hi There - Clojure noob here. I wanted to ask some question about games
> programming in Clojure.  Is it ok to ask here or is there a better spot?
> Most of my questions aren't super game-specific.
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: Writing a text adventure in Clojure

2018-03-29 Thread James Reeves
Often it's better to store the entire game state as one large, immutable
data structure.

Atoms are usually preferred over refs in most cases.

When you want polymorphism over a map, the most common solution is to use
protocols and records.


On 29 March 2018 at 23:45, Will Duquette <w...@wjduquette.com> wrote:

> I'm an experienced programmer, but a Clojure newbie; as a beginner
> project, I'm looking into how one would idiomatically write a text
> adventure of sorts in Clojure.  I'm less interested in producing a playable
> game than I am in learning how to do such a thing in a proper functional
> style.
>
> Suppose in this game I have a room whose description changes based on a
> global flag.  For example, there's something in the Fancy Room that you
> won't notice until you've reached the major plot point.
>
> The world map is (for the sake of argument) a hash-map whose keys are the
> room IDs and whose values are room records, where each record is a hash-map.
>
> (def world {:fancy-room {:name "Fancy Room" :description "This is a fancy
> room." ...}})
>
> I'm aware that I could use a (defstruct) or (defrecord); I'm keeping it
> simple for now.  Then, the flags are saved in a ref; the intent is that
> mutable set is segregated, so that it can more easily be written to a save
> file.
>
> ;; Global set of flags
> (def flags (ref #{})
>
> (defn flag-set [flag]
>(dosync (alter flags conj flag))
>
> ;; When the major plot point is reached
> (flag-set :major-plot-point-reached)
>
> Normally, to describe a room you just return its :description.
>
> (defn describe [room] (:description (world get room)))
>
> But for the :fancy-room, the returned description depends on the global
> flag, and it will be specific to :fancy-room.  I could add this logic
> directly to the (describe) function's body, but that would be ugly.  What
> I'd like to do is attach a lambda to the :fancy-room in some way.  The
> (describe) function looks for a :describer, and if it's there it calls it;
> and if not it just returns the :description:
>
> (defn describe [entity]
> (if (:describer entity)
>   ((:describer entity) entity)
>   (:description entity)))
>
> *Question 1*: this works, but it looks ugly to me; I figure there's a
> better, more idiomatic way to do this kind of thing that's probably obvious
> to anyone with any real experience.  Multimethods, maybe?  Define a Room
> protocol, then let most rooms be NormalRoom records, but let :fancy-room be
> a FancyRoom record?
>
> *Question 2*: Whatever code actually computes the description, it will
> need access to the :major-plot-point-reached flag.  What's the cleanest way
> to give the description code access to the flags ref?  It could simply
> access "@flags" directly:
>
> (if (:major-plot-point-reached @flags)
>   "This is a fancy room.  Hey, that light sconce looks movable!"
>   "This is a fancy room.")
>
> But that doesn't seem properly functional.  Would it be better to pass the
> game state into each method?
>
> (defn describe [entity state]
>   (if (:describer entity)
>  ((:describer entity) entity state)
>  (:description entity)))
>
> Any ideas?
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: lein-codox custom writer

2018-03-05 Thread James Reeves
Leiningen has an "update-in" task for updating the project map on the fly,
so something like:

lein update-in :codox assoc :writer my.custom/writer -- codox

You have to make sure that the custom writer is on the classpath of course,
which may require updating the project file to include new dependencies as
well.

On 5 March 2018 at 18:45, Janko Muzykant <umr...@gmail.com> wrote:

>
> Codox documentation mentions how to set up a custom output writer using
> leiningen :codox option:
>
>   :codox {:writer codox.writer.html/write-docs}
>
> Is there any way to achieve the same without touching project.clj,
> eg. by providing writer location at lein command-line (similarly to what
> boot-codox provides with -w option) and by injecting writer
> implementation into a classpath?
>
> JM.
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: [?] Adding my own function to clojure.core namespace

2018-02-25 Thread James Reeves
On 25 February 2018 at 12:01, Philos Kim <philo...@gmail.com> wrote:

> I know it is not desirable but it is sometimes needed, especially in my
> case.
>
> For example , I wrote debux ( https://github.com/philoskim/debux )
> library. I want to use it only in development, not in production. If I
> 'require' debux in source code to use it in development, I have to remove
> it in the source code manually in production.
>

The normal solution to this is to have a development namespace and a
production namespace that serve as entry points for your application.
During development you load in the dev namespace, and in production the
prod namespace will contain the -main function that starts your application.

You can omit the development namespace and anything it requires from the
production classpath when you compile the jar.

-- 
James Reeves
booleanknot.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.


Re: Help please: New to clojure development

2018-02-05 Thread James Reeves
First:

  (#(map :st_abbrev input-file))

Is equivalent to:

  (map :st_abbrev input-file)

Because your putting the form in an anonymous function, then immediately
calling it. This is equivalent to just evaluating the form.

Next, I think you're confused as to how `map` handles multiple arguments.
If you call:

  (map f [1 2 3] [4 5 6])

Then it will return:

  [(f 1 4) (f 2 5) (f 3 6)]

The two collections are lined up, then passed as arguments to the function.

If you want to put this into one function, then you don't need an inner
map. You instead want:

  (defn state-desc2 [input-file]
(let [desc2 (:st_abbrev input-file)]
(case desc2
 "AZ" (assoc input-file :state "Arizona")
 "FL" (assoc input-file :state "Florida")
 "OH" (assoc input-file :state "Ohio")
 "default")))

You could also write it as:

  (def state-names
{"AZ" "Arizona", "FL" "Florida", "OH" "Ohio"})

  (defn state-desc3 [input-file]
(assoc input-file :state (state-names (:st_abbrev input-file



On 6 February 2018 at 01:22, Nadeen Kurz <kurznad...@gmail.com> wrote:

> Can someone help me with the following please: I am new to clojure and i
> haven't developed in 4 years, previous was mainframe. See questions in blue
>
> ; Task is to add full state name based on st_abbr
>
>
> (def input-file [{:st_abbrev "AZ", :firstname "john", :lastname "smith"}
>   {:st_abbrev "FL", :firstname "roy", :lastname
> "wills"}
>{:st_abbrev "OH", :firstname "jay", :lastname
> "louis"}])
>
> *Question 1: How do I make these between the lines into one Defn?*
> ---
> (def get-state
>   (#(map :st_abbrev input-file)))
>
> #'user/get-state
> ("AZ" "FL" "OH")
>
> (defn state-desc [get-state input-file]
>   (let [desc get-state]
>   (case desc
>"AZ" (assoc input-file :state "Arizona")
>"FL" (assoc input-file :state "Florida")
>"OH" (assoc input-file :state "Ohio")
>"default"
>)))
>
> (map state-desc get-state input-file)
>
> #'user/state-desc
>  ({:st_abbrev "AZ", :firstname "john", :lastname "smith", :state
> "Arizona"}
>   {:st_abbrev "FL", :firstname "roy", :lastname "wills", :state "Florida"}
>   {:st_abbrev "OH", :firstname "ja  y", :lastname "louis", :state "Ohio"})
> 
> ---
>
> Question 2: I tried to combine in one defn, but it's not working, any help
> would be appreciated
>
> (defn state-desc2 [input-file]
>   (let [desc2 (#(map :st_abbrev input-file))]
>   (case desc2
>"AZ" (assoc input-file :state "Arizona")
>"FL" (assoc input-file :state "Florida")
>"OH" (assoc input-file :state "Ohio")
>"default"
>)))
>
> (map state-desc2 input-file)
>
> #'user/state-desc2
> ("default" "default" "default")
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: what does future do after fn finish ?

2018-01-31 Thread James Reeves
On 31 January 2018 at 17:59, Jacek Grzebyta <grzebyta@gmail.com> wrote:

> I have application with quite intense tripe store populating ~30/40 k
> records per chunk (139 portions). The data are wrapped within the future:
>
> (conj agent (future (apply task args)))
>
>  and that all together is send-off into (agent []).
>

What is "agent"? The first line of code indicates that it's a local
collection shadowing the code function, while the second code snippet
indicates that you're using the core agent function.

Also why are you sending off to an agent?

At the end of the main thread function I just use await-for and after that:
>
> (reduce + (map #(deref %) @data-loading-tasks))
>
> For some reason I see the happy collecting (see attached screenshot of
> jconsole).
>

"happy" = "heap"?


> After seeing the source code of future I suppose that the memory (data are
> kept as #{} set) is not released. The task returns only integer so I do not
> think that might cause the problem.
>

Can you provide more detail? You keep alluding to things that you don't
provide code for, such as the sets of data.

-- 
James Reeves
booleanknot.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.


Re: Is str's behavior changed?

2018-01-14 Thread James Reeves
The str function has always behaved in the same way. The article is
somewhat misleading.

The article does say "strings print without the surrounding quotes", which
is true if you're using the function "print" or "println":

  user=> (println "Hello World")
  Hello World
  nil

But REPLs print the representation of the evaluated expression. They use
"pr" instead of "print" and "prn" instead of "println":

  user=> (prn "Hello World")
  "Hello World"
  nil

  user=> "Hello World"
  "Hello World"


On 15 January 2018 at 04:26, Alice <dofflt...@gmail.com> wrote:

> Unlike explained in http://blog.klipse.tech/clojure/2016/11/24/stringify-
> clojure.html (str "Hello\nWorld") just prints "Hello\nWorld"(Surrounding
> quotes are preserved and new lines are not interpreted). String.toString()
> just returns the string itself, so I have no idea why it should be the way
> explained in the post in the first place.
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: What's up with IMeta?

2017-11-05 Thread James Reeves
On 5 November 2017 at 21:32, Michał Marczyk <michal.marc...@gmail.com>
wrote:

> Now, if xs' head has not been realized, (with-meta xs {:foo 1}) can
> conceivably operate in one of two ways:
>
> 1. it can copy over xs' thunk (the nullary function embedded in the lazy
> seq object xs that is called – and expected to return a sequence or nil –
> when xs needs to be realized) into a new lazy seq object ys;
>
> 2. it can realize the head of xs and call .withMeta on the result.
>
> The first approach, however, breaks the promise that realizing the head of
> xs will have the effect of realizing the head of ys, as neither xs nor ys
> would subsequently have any way of knowing whether the other's head has
> been realized when they finally need to realize their own heads, and so the
> second one to be realized would be forced to recompute the sequence.
>
> Thus the implementation takes the second approach.
>

Why can't it just memoize the thunk when creating a new instance?

-- 
James Reeves
booleanknot.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.


Re: What's up with IMeta?

2017-11-04 Thread James Reeves
On 5 November 2017 at 00:57, Didier <didi...@gmail.com> wrote:

> I think I'm firstly confused by the use of the word object. I'm guessing
> in this case it refers to things that implement IObj?
>

It means an object on the JVM.


> I'm then confused by what is meant that an object with different meta is a
> different object, if they are still equal?
>

Two objects can be equal, yet refer to two different locations in memory.
For example:

  user=> (def a (java.net.URI. "/foo"))
  #'user/a
  user=> (def b (java.net.URI. "/foo"))
  #'user/b

Here are two objects that are equal, but they each have a different
location in memory:

  user=> a
  #object[java.net.URI 0xf20da5a "/foo"]
  user=> b
  #object[java.net.URI 0x290826b7 "/foo"]

When two symbols reference the same object in memory, we say they are
*identical*. In this case, a and b are *equal* but not *identical*.

  user=> (identical? a b)
  false
  user=> (= a b)
  true

I'm guessing it means that if you change the meta on an IObj, you get a
> copy?
>

It's more accurate to say that an IObj's metadata cannot be changed; you
can only create a new IObj with new metadata.

And then I'm confused as to why that would cause lazy-seq to realize their
> head? Can't two lazy-seq share the same head?
>

This I'm not too certain about. It may just be an implementation detail.

-- 
James Reeves
booleanknot.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.


Re: What's up with IMeta?

2017-11-04 Thread James Reeves
On 3 November 2017 at 06:57, Didier <didi...@gmail.com> wrote:

> Okay, I can see how I can maybe infer some of that by piecing together the
> code base, but if there was a book, or a reference somewhere describing
> more the implementation of Clojure itself I'd be interested to read it, if
> there is one out there. I'd understand if there's not, I know Clojure has
> no formal semantic spec.
>

I don't know of one, I'm afraid.


> Also, I guess I'm still confused about that bit:
>
> > That said, metadata and its relationship to an object is immutable - an
> object with different metadata is a different object. One consequence of
> this is that applying metadata to a lazy sequence will realize the head of
> the sequence so that both objects can share the same sequence.
>

What confuses you about it? Is it the "realize the head of the sequence"
part?

-- 
James Reeves
booleanknot.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.


Re: What's up with IMeta?

2017-11-02 Thread James Reeves
On 3 November 2017 at 02:31, Didier <didi...@gmail.com> wrote:

> Wow, thanks. Is that all tribal knowledge? Or is there some documentation
> around the Clojure interfaces and their semantics somewhere I could read?
> Maybe even a Clojure book recommendation that covers this?
>

Each of the internal methods corresponds to an public function:

  IMeta.meta => clojure.core/meta
  IObj.withMeta  => clojure.core/with-meta
  IRef.alterMeta => clojure.core/alter-meta!
  IRef.resetMeta => clojure.core/reset-meta!

So in the case of the metadata interfaces, it's pretty straightforward to
figure out what they do by reading the API docs.


> So if I understand correctly, withMeta will return a new object which is
> not equal to the old. So two immutable objects implementing IObj which
> differ only in meta are not equal. But this is a convention, in that if I
> implement IMeta myself, I should also override equals so that it returns
> false when meta differs correct?
>

Metadata doesn't affect equality (see the docs on metadata
<https://clojure.org/reference/metadata>), so even though the object
*identity* will differ when you use with-meta, they will be considered to
be equal:

  user=> (def m1 {:a 1})
  #'user/m1
  user=> (def m2 (with-meta m1 {:x 2}))
  #'user/m2
  user=> (= m1 m2)
  true
  user=> (identical? m1 m2)
  false

-- 
James Reeves
booleanknot.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.


Re: What's up with IMeta?

2017-11-01 Thread James Reeves
IMeta only allows you to read metadata.
IObj is for immutable data that can be duplicated with new metadata.
IReference is for references.

So an immutable map would implement IObj, but an atom would implement
IReference.

If you want to support metadata, you need to decide what type of object it
is; is it mutable or immutable?

On 2 November 2017 at 01:20, Didier <didi...@gmail.com> wrote:

> Hey, I was surprised to find that IMeta does not work for (with-meta).
>
> So it seems that withMeta is added to IObj, which extends IMeta. And it
> seems like alterMeta and resetMeta are added in IReference, which also
> extends IMeta.
>
> So now if you want to support meta, you have to implement IReference, IObj
> and IMeta?
>
> Is there a reason for this? Particularly, I find it strange I can't use
> with-meta on a Var, because it only implements IReference, and not IObj. So
> I can use all meta functions on Vars except for with-meta.
>
> Thank you.
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: Using ring, jetty plugin: No reader function for tag object

2017-10-22 Thread James Reeves
It looks like there's a dependency mismatch between the version of Ring
that Lein-Ring injects, and the version you've added to your project file.
If you update Ring to 1.6.2 (and lein clean) it should work.

On 22 October 2017 at 18:40, Angel Java Lopez <ajlopez2...@gmail.com> wrote:

> Hi!
>
> I have a problem, following the instructions:
>
> https://github.com/ring-clojure/ring/wiki/Getting-Started
>
> I can run the server using the repl
>
> But when I added the plugin, according to:
>
> https://github.com/ring-clojure/ring/wiki/Interactive-Development
>
> and execute
>
> lein ring server
>
> I get the infamous error:
>
> Exception in thread "main" java.lang.RuntimeException: No reader function
> for tag object, compiling::
> at clojure.lang.Compiler.load(Compiler.java:7386)
> at clojure.lang.Compiler.loadFile(Compiler.java:7317)
> at clojure.main$load_script.invokeStatic(main.clj:275)
> at clojure.main$init_opt.invokeStatic(main.clj:277)
> at clojure.main$init_opt.invoke(main.clj:277)
> at clojure.main$initialize.invokeStatic(main.clj:308)
> at clojure.main$null_opt.invokeStatic(main.clj:342)
> at clojure.main$null_opt.invoke(main.clj:339)
> at clojure.main$main.invokeStatic(main.clj:421)
> at clojure.main$main.doInvoke(main.clj:384)
> at clojure.lang.RestFn.invoke(RestFn.java:421)
> at clojure.lang.Var.invoke(Var.java:383)
> at clojure.lang.AFn.applyToHelper(AFn.java:156)
> at clojure.lang.Var.applyTo(Var.java:700)
> at clojure.main.main(main.java:37)
> Caused by: java.lang.RuntimeException: No reader function for tag object
> at clojure.lang.LispReader$CtorReader.readTagged(
> LispReader.java:1245)
> at clojure.lang.LispReader$CtorReader.invoke(LispReader.java:1228)
> .
>
> Using Windows 10, JDK 1.8_074
>
> Current project at:
>
> https://github.com/ajlopez/ClojureSamples/tree/master/Ring/helloring
>
> I tried other tutorials, examples, using the REPL is OK, but using the
> plugin and lein ring server, does not work
>
> Notable, other ring plugin commands work, like lein ring uberjar
>
> Any cues??
>
> TIA
>
> Angel "Java" Lopez
> @ajlopez
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: An idea to improve foundations of documentation in clojure

2017-10-17 Thread James Reeves
A better place for this is on the var's metadata, which is where the
docstring, arglist, etc. are already stored.

On 17 October 2017 at 20:16, Sameer Rahmani <lxsame...@gmail.com> wrote:

> Hi all.
>
> First of all thanks all you guys because of Clojure/Clojurescript and all
> the fantastic tools and libraries around it.
>
> Certainly Clojure documentation needs an improvement. But to be honest
> there is no good tool in the community of Clojure or even any other
> communities to do that. Any tools out there has it's own pros and cons.
>
> Put the tooling aside writing documentation is not fun and there is no
> specific set of rules regarding to write docs in Clojure. IMO having a set
> of rules is not going to help us. What we need is a robust foundation which
> provides necessary means for tools and document generators or developers to
> write and generate decent documentation.
>
> As all of you know Clojure.spec rocks. We already saw that the community
> quite love clojure.spec ( there might be some people not agree with me ).
> Since the first time I used spec in my code I was thinking that how awesome
> would it be for Spec to support documentation as well, and not just by
> adding strings to spec ( which would be the same as docstrings and not
> enought ). I was thinking, we can treat docs as data as well and include
> them in our specs in a certain way which allows developers and tools to use
> them in their own way. For example we can include more stuff in
> `clojure.spec/fdef` in order to describe the function in question.
> Something like:
>
> (s/fdef  some-fn
>  :args ()
>  :ret 
>  :fn 
>  :short-desc "some string which can be formatted using :args"
>  :long-desc "some long description which may contains references
> and other stuff"
>  :refrences [::other-fn]
>  :other-necessary-keys-for-docs)
>
> The above code is just a demonstration of what i had in mine.
>
> But this way we can describe the documentation of our code by data and it
> would be really easy for doc generators to fetch the spec of each symbol
> from spec registry and ask for the documentation data on that symbol and
> generate the documentation base on that data.
>
> Also it would be easy for devs to write docs and specs would be a
> foundation and a practical set of rules to write docs. It is also backward
> compatible, because docstrings can live to fulfill their purpose and from
> now on we can start using this new feature to generate sophisticated docs .
>
> Describing documentation as data would help tools like cider and cursive
> to be more helpful as well.
>
> I really like to know your thoughts on this topic.
>
> At the end sorry for the long post and I'm not a native English speaker so
> there is a good chance that I did a bad job expressing my thoughts.
>
> Cheers
> Sameer
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: hello world question !!!

2017-10-13 Thread James Reeves
The docstring for compile
<https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/compile>
says that "The source for the lib must be in a proper
classpath-relative directory", so unfortunately you can't just create the
namespace in the REPL and compile it from there. The tutorial on the
Clojure site doesn't make that as clear as it could be.

In your revised example, you're setting the classpath incorrectly. The
classpath should contain the root of your file tree. For example, if you
have the file path "src/clojure/examples/hello.clj", then the classpath
should be set to "src".

I'm not sure how the "clojure" script you're running works, but you might
find Leiningen to be a better starting point. In Clojure 1.9, an official
"clj" script is going to be introduced, which might make this process
easier. Until then, Leiningen is probably the safer bet.

On 13 October 2017 at 18:13, Damien Mattei <damien.mat...@gmail.com> wrote:

> i did not have , i just follow the tutorial:
> https://clojure.org/reference/compilation
> i made the file but still the same problem:
>
> [mattei@moita ~]$ export CLASSPATH=.:./clojure/examples
> [mattei@moita ~]$ clojure
> Clojure 1.5.1
> user=> (compile 'clojure.examples.hello)
> FileNotFoundException Could not locate clojure/examples/hello__init.class
> or clojure/examples/hello.clj on classpath:   clojure.lang.RT.load
> (RT.java:443)
> user=> ^C[mattei@moita ~]$
>
> [mattei@moita ~]$ cat clojure/examples/hello.clj
> (ns clojure.examples.hello
> (:gen-class))
>
> (defn -main
>   [greetee]
>   (println (str "Hello " greetee "!")))
>
> On Friday, October 13, 2017 at 4:48:40 PM UTC+2, James Reeves wrote:
>>
>> Maybe this is a dumb question, but do you have a file
>> "clojure/examples/hello.clj" on the classpath? Since that's what the
>> exception is complaining about.
>>
>> On 13 October 2017 at 15:09, Damien Mattei <damien...@gmail.com> wrote:
>>
>>> hello,
>>>
>>> i'm new to clojure, just installed it on a CentOS box,
>>>
>>> and try to compile the code below from tutorial, but it does not work, i
>>> searched a lot before posting, no answer... i do not want to use leiningen
>>> at this stage,later perheaps...
>>>
>>> just want to compile and run
>>>
>>> user=> (ns clojure.examples.hello
>>> (:gen-class))
>>> nil
>>> clojure.examples.hello=>
>>> clojure.examples.hello=> (defn -main
>>>   [greetee]
>>>   (println (str "Hello " greetee "!")))
>>> #'clojure.examples.hello/-main
>>> clojure.examples.hello=> (compile 'clojure.examples.hello)
>>> FileNotFoundException Could not locate clojure/examples/hello__init.class
>>> or clojure/examples/hello.clj on classpath:   clojure.lang.RT.load
>>> (RT.java:443)
>>>
>>> help greatly appreciated (because i'm just one step to leave Clojure and
>>> continue using  Kawa or Bigloo i already use or dive into ABCL , but
>>> Clojure has a so good reputation, i cannot imagine being sticked here by a
>>> simple hello world!)
>>>
>>> damien
>>>
>>> --
>>> 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.
>>>
>>
>>
>>
>> --
>> James Reeves
>> booleanknot.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 t

Re: hello world question !!!

2017-10-13 Thread James Reeves
Maybe this is a dumb question, but do you have a file
"clojure/examples/hello.clj" on the classpath? Since that's what the
exception is complaining about.

On 13 October 2017 at 15:09, Damien Mattei <damien.mat...@gmail.com> wrote:

> hello,
>
> i'm new to clojure, just installed it on a CentOS box,
>
> and try to compile the code below from tutorial, but it does not work, i
> searched a lot before posting, no answer... i do not want to use leiningen
> at this stage,later perheaps...
>
> just want to compile and run
>
> user=> (ns clojure.examples.hello
> (:gen-class))
> nil
> clojure.examples.hello=>
> clojure.examples.hello=> (defn -main
>   [greetee]
>   (println (str "Hello " greetee "!")))
> #'clojure.examples.hello/-main
> clojure.examples.hello=> (compile 'clojure.examples.hello)
> FileNotFoundException Could not locate clojure/examples/hello__init.class
> or clojure/examples/hello.clj on classpath:   clojure.lang.RT.load
> (RT.java:443)
>
> help greatly appreciated (because i'm just one step to leave Clojure and
> continue using  Kawa or Bigloo i already use or dive into ABCL , but
> Clojure has a so good reputation, i cannot imagine being sticked here by a
> simple hello world!)
>
> damien
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: CLJS: experiencing "callback envy" re closures as DOM event handlers

2017-10-11 Thread James Reeves
If you output your HTML as DOM nodes, rather than a string, you can just
attach the function directly to the attribute.

On 11 October 2017 at 18:20, hiskennyness <kentil...@gmail.com> wrote:

> I am cobbling together my own little CLJS web framework and it is going
> well but I am stumped by one bit of interop: supporting event handlers that
> close over lexical variables. It seems to be a piece of cake for, inter
> alia, Reagent. Here is an excerpt from the "simple" example, hacked a bit
> (the "xxx" bits) to make sure I was seeing what I was seeing:
>
> (defn color-input []
>   (let [xxx (atom 0)]
> [:div.color-input
>  "Time color: "
>  [:input {:type  "text"
>   :value @time-color
>   :on-change #(do (reset! xxx (rand-int 32767))
>   (println :xnow @xxx)
>   (reset! time-color (-> % .-target 
> .-value)))}]]))
>
>
> My approach is to convert the anonymous function to  a string via STR and
> specify it in the generate HTML as the handler. Just to see my html I have
> a little test code:
>
> (let [xxx (atom 42)]
>   (println :htm!!! (tag/to-html [(h1 {:onclick (on-evt #(swap! xxx inc))} 
> "Help!")])))
>
>
> Here is `on-evt`:
>
> (defn on-evt [cbfn]
>   (cl-format nil
> "(~a)(event)"
> (str cbfn)))
>
>
> Here is what I see in the console:
> :htm!!! Help!
>
> But JS understandably does not see the  "xxx_12780".
>
> I have tried more than once digging into the reagent code to see how it is
> working its magic but always run into a dead end.
>
> The one thing I do see when I inspect the DOM in the Chrome debugger is
> that the handler is not there on the target element, just a react-id or
> some such. This makes me think that the anonymous function itself (happily
> compiled into JS closed over the lexical variable) is being stashed in a
> dictionary under the react-id and that a handler at the document level is
> navigating from the event target to the closure via the react-id.
>
> That's just crazy enough to work. :) But am I just missing some simple
> CLJS interop capability? Any other ideas?
>
>
>
>
>
>
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: Question about Clojure parallelization

2017-09-12 Thread James Reeves
As you suspect, your Clojure code isn't very performant.

First, you're doing lots of updates to an immutable map, which isn't going
to be efficient. Clojure allows immutable data structures to be changed,
temporarily, into mutable ones using the transient function. Alternatively,
sometimes it's worth falling back to mutable Java structures like
Hashtables.

You can work out the frequencies of the patterns a little more concisely
with:

  (defn pattern-frequencies [line]
(->> (range 12)
 (mapcat #(partition (inc %) 1 line))
 (map str/join)
 (frequencies))

And then combine them with:

  (defn merge-frequencies [freqs]
(merge-with + freqs))

There's plenty of room for optimisation there, but making more use of
Clojure's core functions is an easy way to make things quicker.


On 12 September 2017 at 16:54, <darren92@gmail.com> wrote:

> Hi,
>
> I am a researcher of Natural Language Processing.
> My team want to know how well does Clojure parallelize and how much time
> is reduced compared by Java single thread version.
>
> The problem we want to solve is,
> there is a big corpus file (just now 500MB).
> Reading sentences line by line, find all patterns and their occurrence
> count on length 1 through 12.
>
> It is a very simple problem and It doesn’t care of order of processing.
> We want to make just a big hash-map. (Key is a pattern string, Value is a
> occurrence count.)
> Ex) { “father” 1000 “mother” 1000 … }
>
> Comparing performance between Java and Clojure, if Clojure version is
> better than Java,
> then we’ll change our code base to Clojure, if not, we cannot help staying
> Java.
>
> Anyway my first prototype is very very slow. I’m a novice.  :(
>
> Please give me some advices.
> Thanks.
>
> (ns parallel-test.core
>  (:require [clojure.java.io :as jio]
>[clojure.core.reducers :refer [fold]])
>  (:gen-class))
>
> (def corpus-file-url "resources/korean.txt")
> (def OC (atom nil))
> (def MPL 12)
> (def each-size 1)
>
> (defn add-pattern-to-hashmap
>  [h-map ^String ptn ^Integer ptn-oc]
>  (let [h-ptn-oc (get h-map ptn)
>n-ptn-oc (if (nil? h-ptn-oc)
>  ptn-oc
>  (+ h-ptn-oc ptn-oc))]
>   (assoc h-map ptn n-ptn-oc)))
>
> (defn merge-hash-map
>  ([] (hash-map))
>  ([& hs]
>   (reduce (fn [l-map r-map]
>(reduce (fn [[ptn ptn-oc]]
> (add-pattern-to-hashmap l-map ptn ptn-oc))
>r-map))
>   hs)))
>
> (defn cal-line-oc
>  ([] (hash-map))
>  ([h-map ^String line]
>   (let [line-length (count line)]
>(loop [i 0
>   i-map h-map]
> (if (>= i line-length)
>  i-map
>  (recur (inc i)
> (loop [j 1
>j-map i-map]
>  (let [end-index (+ i j)]
>   (if (or (> j MPL) (> end-index line-length))
>j-map
>(recur (inc j)
>   (add-pattern-to-hashmap j-map (subs line i end-index) 
> 1)))
>
> (defn parallel-process
>  [combine-fn reduce-fn input-file]
>  (with-open [rdr (jio/reader input-file)]
>   (fold each-size
> combine-fn
> reduce-fn
> (line-seq rdr
>
> (defn -main [& args]
>  (println "start")
>  (reset! OC (parallel-process merge-hash-map cal-line-oc corpus-file-url))
>  (println "end"))
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: SRSLY? (= (true? identity) (false? identity)) => true

2017-09-02 Thread James Reeves
On 2 September 2017 at 05:06, Rostislav Svoboda <rostislav.svob...@gmail.com
> wrote:

> > identity isn't a boolean, so neither true? nor false? should return true
> for it
>
> But then why it should return 'false'?


Because you're asking, "Is identity the boolean value true?", and Clojure
is telling you, "False, it's a function".

Then you ask "Is identity the boolean value false?", and clojure replies,
"Also false, it's still a function.".

Then finally you ask, "Is false equal to false?" and Clojure says, "True."

-- 
James Reeves
booleanknot.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.


Re: Sum types in Clojure? Better to represent as tagged records or as variant vectors?

2017-08-22 Thread James Reeves
On 23 August 2017 at 05:15, Timothy Baldridge <tbaldri...@gmail.com> wrote:

> Simple: because failing to put it in a map constrains future growth.
>

Sometimes that's what you want. A constrained function is a simple function.

Should (find {:a 1} :a) produce {:key :a, :val 1} instead of [:a 1]? No,
because it doesn't need to be extensible.

And for that matter, where do we stop? Should:

  {:person/score 89}

Be:

  {:person/score {:val 89}}

Just in case we want to extend it in future?

  {:person/score {:val 89, :max 100}}

Any argument about extensibility around [[k v]] also applies to {k v}.

But I guess I'd flip it around. Why would I ever want:
>
> [:response val]
>
> when I could have
>
> {:status :response
>  :result val}
>

Well, going purely by syntax, it's more concise, (IMO) more readable,
easier to match and destruct, and intrinsically compatible with "into" like
functions:

  (def latest-values (async/into {} ch))

I don't see how you can say {k v} is somehow fine, but a stream of [k v]
pairs over time is somehow bad.

-- 
James Reeves
booleanknot.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.


Re: Sum types in Clojure? Better to represent as tagged records or as variant vectors?

2017-08-22 Thread James Reeves
On 23 August 2017 at 04:27, Timothy Baldridge  wrote:

> But Datomic has E in [e a v] which links multiple [a v] pairs into an
> entity...which is basically a map. So I don't think that applies here.
>

Except that [e a v t] facts in Datomic are ordered and not necessarily
unique, and that's my part of my point. A collection/stream of variants (or
tuples that contain some manner of [k v] part) are map-like but often have
additional properties, such as ordering.


>   GET /example HTTP/1.1
>   Host: www.example.com
>
>   [:request/method :get]
>   [:request/uri "/example"]
>   [:request/protocol "HTTP/1.1"]
>   [:request/header ["host" "www.example.com"]]
>
> Once again, a ad-hoc encoding. What is "GET", what is "/example". I see
> that datastructure and all I see are hashmaps.
>
> Do it the way ring does ;-)
>
> {:method :get
>  :uri "..."
>  :headers [...]}
>

And what happens if I want to stop processing the request the moment I hit
the request method? For example:

  (fn [req]
(go
  (match (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: Sum types in Clojure? Better to represent as tagged records or as variant vectors?

2017-08-22 Thread James Reeves
On 23 August 2017 at 03:58, Timothy Baldridge <tbaldri...@gmail.com> wrote:

> Put let's take that and look at it under a engineering lens a bit:
>
> >> For example, a series of events that represent a player's moves in a
> card game:
> >>
> >>  [:card/draw :9h]
>
> You have an ad-hoc encoding of data here now. Expand it out a bit, and
> make it machine readable instead of preferring ease of writing and you get:
>
> {:player/action :card/draw
>  :card/number :9
>  :card/suit :hearts}
>
> Much easier to introspect, and extensible as future data just flows
> through without existing code breaking because you add extra data.
>

But possibly over-engineered. Suppose that the only function we want to
produce is:

  (cards-in-hand events)
  => #{:9h :qh :7d}

If we have a function that returns [k], [v] or {k v}, then I have a hard
time buying the idea that the input to the function should be more complex
than [[k v]].

If the scope of the data is not so constrained, then sure, use a map.

>> I've also found it a useful pattern for data access:
> >>
> >>  [:data/found "Bob"]
>
> I've worked with systems that have done this, and I really dislike it.
> Because now I have to zip the inputs of a function with the outputs if I
> want a composable system usable in pipelines and the like.
>
> What's much better:
>
> {:op/status :success
>  :data/found "Bob"
>  :data/key "444-434-3323"
>  :server/ip }
>
> Now not only do I know what data I got, but where it came from, the key I
> originally used, etc.
>

Which is useful only if you plan on using that additional data. If you are
only ever interested in the key and value, and the function is internal,
why dress it up?

-- 
James Reeves
booleanknot.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.


Re: Sum types in Clojure? Better to represent as tagged records or as variant vectors?

2017-08-22 Thread James Reeves
On 23 August 2017 at 03:48, Didier <didi...@gmail.com> wrote:

> I can see it be quick and concise for representing events, but that's also
> exactly the use case example for multi-spec: https://clojure.
> org/guides/spec#_multi_spec
>
> What happens if your event needs more data? Maybe draw needs 2 attributes,
> the card and the deck? Now you have implicit encoding, where what the
> attributes are for the event are defined by its position in the vector.
>

Sometimes it's an advantage to have a deliberately constrained format,
particularly when it comes to storage or indexing. Datomic, for instance,
is effectively an indexed event log of [e a v t] tuples.

If you're in a situation where the event data can and may expand, then use
a map. But I'd argue that there are situations where the scope is limited,
or you want a deliberate and hard constraint on what data is in an event.

Another possible situation is if you're parsing map data incrementally. For
example, a Ring request map could be read in as a series of key/value pairs:

  GET /example HTTP/1.1
  Host: www.example.com

  [:request/method :get]
  [:request/uri "/example"]
  [:request/protocol "HTTP/1.1"]
  [:request/header ["host" "www.example.com"]]

I'm not saying that variants should be favoured over maps in all
situations; just that there are situations where you're certain that you
need key/value pairings.

-- 
James Reeves
booleanknot.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.


Re: Sum types in Clojure? Better to represent as tagged records or as variant vectors?

2017-08-22 Thread James Reeves
On 23 August 2017 at 01:18, Timothy Baldridge <tbaldri...@gmail.com> wrote:

> Great, so these approaches are suggesting we wrap every value in a vector
> or a hash map (as the lisp cast article does).
>

What? No, that's not what I'm saying at all.

If you have an unordered collection of key/value pairs where every key is
unique, then *of course* you use a map.

But if you have only *one* key/value pair, how do you represent that? Or if
you want an arbitrarily ordered collection of key/value pairs? Or a
collection with repetition?

For example, a series of events that represent a player's moves in a card
game:

  [:card/draw :9h]
  [:card/draw :qh]
  [:card/draw :4s]
  [:card/discard :4s]
  [:card/draw :7d]

I've also found it a useful pattern for data access:

  [:data/found "Bob"]
  [:data/not-found]
  [:data/unauthorized]
  [:data/retry-in 600]

A [k v] vector isn't the only way of representing data like this, but it is
probably the most concise.

-- 
James Reeves
booleanknot.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.


Re: Sum types in Clojure? Better to represent as tagged records or as variant vectors?

2017-08-22 Thread James Reeves
On 22 August 2017 at 23:04, Timothy Baldridge <tbaldri...@gmail.com> wrote:

> I find the arguments for variants very unconvincing. As you stated with
> specs and s/keys you can spec the same sort of data, and in a way that's
> much more open-ended.
>
> For example:
>
> [:person {:name "Tim" :grade "B"}]
>
> What is the type of this data? We would probably guess a :person. But what
> if we wanted to "cast" it to a :student? Well then we'd have to change the
> variant tag to :student, but then it would no longer be a person, unless we
> introduced some sort of inheritance that said all students are people.
>

I don't think that example is a representative use of variants in Clojure.
More typically, variants are used like key/value pairings that exist
outside a map. For example:

  [:person/name "Tim"]

If you actually have a map, the key/value pairs speak for themselves:

  #:person{:name "Tim", :grade "B"}

We can tell this is a "person" because it adheres to a particular shape,
which can be specced out:

  (s/def :person/student (s/keys :req [:person/name :person/grade]))

But if you just have a key/value pairing, the value alone doesn't tell you
much:

  "Tim"

Using a vector to represent a key/value seems to fit in well with how
Clojure currently works:

  (find m :person/name)
  => [:person/name "Tim"]

But there's no "s/variant" or "s/entry" spec that's as convenient to use as
s/keys.

-- 
James Reeves
booleanknot.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.


Re: Entity–component–system and Clojure

2017-08-15 Thread James Reeves
scr...@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.
>



-- 
James Reeves
booleanknot.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.


Re: Why is Clojure slow? (fibonacci)

2017-08-13 Thread James Reeves
With type hints your implementation should run faster:

(defn fib ^long [^long n]
  (if (< n 2)
n
(+ (fib (- n 2)) (fib (- n 1)

What does your Java code look like? Is it also recursive?


On 13 August 2017 at 10:54, Daniel Gerlach <daniel.gerlach1...@gmail.com>
wrote:

> Hey,
>
> out of curiosity i did some benchmarking on my Macbook Pro 13 i5 2,7 GHz.
>
> I chose a simple naive fibonacci implementation as a candidate
> (i know that is not a good comparison value for real-world cases)
>
> The implementation looks like this:
>
> (defn fib [n]
>   (if (< n 2)
> n
> (+ (fib (- n 2)) (fib (- n 1)
>
>
>
> The results are a little bit surprising.
>
> The average time for fib(32) in Clojure was ~ 500ms
> The same algorithm in Java takes ~ 15 ms to finish.
> That means Clojure it's ~30x slower than Java for this special case.
>
> I also "warmed up" the JVM in both cases. For Clojure i used "criterium".
>
>
> Can somebody explain? Do i do something wrong? Are there any optimization
> <http://www.dict.cc/englisch-deutsch/optimization.html>s possible, e.g.
> type hints etc. ?
> Does Clojure has problems with recursive functions?
>
>
> Greetings
>
> Daniel Gerlach
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: Bizzarre cond-> behavior

2017-07-21 Thread James Reeves
I can also confirm, tested on Clojure 1.8.0. The macro doesn't seem to take
long at all; it's the expanded code that takes a significant time to
compile.

On 21 July 2017 at 10:56, Peter Hull <peterhul...@gmail.com> wrote:

> On Friday, 21 July 2017 00:35:00 UTC+1, Milt Reder wrote:
>>
>> Here's a simplified example:
>>
>> I can confirm that pasting that defn into a CIDER repl does take a long
> time before the prompt comes back. I tried doing a "macro expand all" and
> it was pretty much instantaneous. The resulting expansion is quite long but
> not unreasonable (see below). Beyond that, I'm not sure how to analyse what
> Clojure's doing or time it. I'm using 1.9 alpha by the way.
> Pete
>
> (def wat
>  (fn*
>([& p__9335]
>  (let*
>[map__9336
> p__9335
> map__9336
> (if (seq? map__9336)
>   (. clojure.lang.PersistentHashMap create (seq map__9336))
>   map__9336)
> a
> (get map__9336 :a)
> b
> (get map__9336 :b)
> c
> (get map__9336 :c)
> d
> (get map__9336 :d)
> e
> (get map__9336 :e)
> f
> (get map__9336 :f)
> map-0
> (get map__9336 :map-0)
> map-1
> (get map__9336 :map-1)
> map-2
> (get map__9336 :map-2)]
>(let*
>  [G__9337
>   "foo"
>   G__9337
>   (if a (str G__9337 a) G__9337)
>   G__9337
>   (if b (str G__9337 b) G__9337)
>   G__9337
>   (if c (str G__9337 c) G__9337)
>   G__9337
>   (if d (str G__9337 d) G__9337)
>   G__9337
>   (if e (str G__9337 e) G__9337)
>   G__9337
>   (if f (str G__9337 f) G__9337)
>   G__9337
>   (if map-0
> (let*
>   [G__9338
>G__9337
>G__9338
>(if (:a map-0) (str G__9338 (:a map-0)) G__9338)
>G__9338
>(if (:b map-0) (str G__9338 (:b map-0)) G__9338)
>G__9338
>(if (:c map-0) (str G__9338 (:c map-0)) G__9338)]
>   (if (:d map-0) (str G__9338 (:d map-0)) G__9338))
> G__9337)
>   G__9337
>   (if map-1
> (let*
>   [G__9339
>G__9337
>G__9339
>(if (:a map-1) (str G__9339 (:a map-1)) G__9339)
>G__9339
>(if (:b map-1) (str G__9339 (:b map-1)) G__9339)
>G__9339
>(if (:c map-1) (str G__9339 (:c map-1)) G__9339)]
>   (if (:d map-1) (str G__9339 (:d map-1)) G__9339))
> G__9337)]
>  (if map-2
>(let*
>  [G__9340
>   G__9337
>   G__9340
>   (if (:a map-2) (str G__9340 (:a map-2)) G__9340)
>   G__9340
>   (if (:b map-2) (str G__9340 (:b map-2)) G__9340)
>   G__9340
>   (if (:c map-2) (str G__9340 (:c map-2)) G__9340)]
>  (if (:d map-2) (str G__9340 (:d map-2)) G__9340))
>G__9337))
>
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: Control Break in Report

2017-07-15 Thread James Reeves
Partition the data. At its simplest:

  (doseq [accounts (partition-by first account-funds)]
(doseq [account (first h), fund (second h)]
  (println account fund)
  (println "---"

You can also use destructuring to do without the let clause:

  (doseq [accounts (partition-by first account-funds)]
(doseq [[account fund] accounts]
  (println account fund)
  (println "---")))

And we can merge the two doseqs:

  (doseq [accounts (partition-by first account-funds), [account fund]
accounts]
(println account fund)
(println "---"))


On 15 July 2017 at 23:18, Kevin Kleinfelter <kleinfelter.gro...@gmail.com>
wrote:

> How does one detect a change in a doseq?
>
> I'm trying to do what data processing people would call a control break in
> a report.  I'm printing account + fund names.  My data is sorted by
> account, so each row has a new fund, and accounts change less frequently.
> I'd like to print a separator line when account changes.  In a procedural
> language, I'd set up an old-account variable, and I'd print the separator
> line when account != old-account.
>
> (doseq [h list-of-account-fund-pairs]
>   (let [account (first h)
> fund (second h)
> *(if changed-account)*
> (println "---")
> (println account fund)
>
> Thanks!
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: [ANN] antizer 0.2.0

2017-06-30 Thread James Reeves
This looks like just what I need. Thanks for writing it!

On 30 June 2017 at 04:31, Michael Lim <prior...@gmail.com> wrote:

> https://github.com/priornix/antizer
>
>
> Antizer <https://github.com/priornix/antizer> has just been released. It
> is a ClojureScript library implementing Ant Design <https://ant.design/>
> React components for Reagent and Rum.
>
> Ant Design is an enterprise-class UI design language and React-based
> implementation with the following features:
>
>- An enterprise-class UI design language for web applications.
>- A set of high-quality React components out of the box.
>- Extensive API documentation and examples.
>
> Examples and Documentation
>
>-
>
>Reagent Demo
><https://priornix.github.io/antizer/latest/examples/reagent.html>
>-
>
>Rum Demo <https://priornix.github.io/antizer/latest/examples/rum.html>
>-
>
>Antizer Documentation https://priornix.github.io/antizer/latest/
>-
>
>API Documentation https://priornix.github.io/antizer/latest/api/
>
> Github project: https://github.com/priornix/antizer
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: error in nrepl

2017-06-23 Thread James Reeves
nrepl-jack-in? Do you mean cider-jack-in? AFAIK nrepl-jack-in is from a
very old version of Cider.

On 23 June 2017 at 21:29, <lawrence.krub...@gmail.com> wrote:

> I'm using Emacs on my Mac. I ran "nrepl-jack-in" to load up the repl. I'm
> iterating over a dataset from mysql. My code is very simple, I'm just
> trying to count the words:
>
> (reduce
>
> (fn [map-of-word-count next-name]
> (let [
> words (clojure.string/split next-name #"\s")
> map-of-names-words-with-count (frequencies words)
> ]
> (println map-of-names-words-with-count)
> (merge-with + map-of-word-count map-of-names-words-with-count)
> )
> )
> {}
> names)
>
> I keep getting this message:
>
>
> error in process filter: nrepl-bdecode-buffer: Cannot decode object: 1
> error in process filter: Cannot decode object: 1
> Error running timer `jit-lock-stealth-fontify': (error "Variable binding
> depth exceeds max-specpdl-size")
> timer-relative-time: Variable binding depth exceeds max-specpdl-size
>
>
> Does anyone know what this means?
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: Stubbornly eager results in clojure.java.jdbc

2017-06-19 Thread James Reeves
egroups.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.
>



-- 
James Reeves
booleanknot.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.


Re: How to call Clojure from Java?

2017-06-01 Thread James Reeves
There's a brief section on this on the Clojure website:

https://clojure.org/reference/java_interop#_calling_clojure_from_java

On 2 June 2017 at 01:35, thelmuth <trh...@gmail.com> wrote:

> What is the best way to call a Clojure function from Java?
>
> Most of the resources I have found are either very old or don't go into
> enough detail. I am a Clojure programmer with very little Java background,
> and have been having trouble with the methods I've found, especially
> classpath issues.
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: The simplest way to publish to Clojars?

2017-05-31 Thread James Reeves
The hardest part is setting up GnuPG, and that only needs to be done once
per machine. Leiningen has a guide on it:

https://github.com/technomancy/leiningen/blob/master/doc/GPG.md

Once that's done, deploying is just a single command: "lein deploy clojars".

I believe the process for Boot is similar, except the command is "boot push
--repo clojars".

On 31 May 2017 at 10:07, Jiyin Yiyong <jiyinyiy...@gmail.com> wrote:

> I tried Lein and Boot. It requires several steps and confused me very long
> time at first. After I made it work in Boot then I never want to write the
> configs by myself again.
>
> Now a year has part. What's the simplest way to do it? Can I do that in a
> way as simple as npm?
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: Parentheses and Proto-Repl

2017-05-21 Thread James Reeves
lisp-paredit seems to have some odd interactions with parinfer, and I don't
think you really need it.

My advice would be to remove lisp-paredit and use parinfer exclusively.
Also ensure that "auto-indent" is turned on in your settings.

Parinfer works through indentation, so as long as everything is indented
correctly, the brackets should manage themselves.

On 21 May 2017 at 20:25, Matching Socks <phill.w...@gmail.com> wrote:

>
> Puzzled about parentheses in Atom + Proto-Repl + Parinfer + lisp-paredit,
> the combination recommended in the gist at https://gist.github.com/
> jasongilman/d1f70507bed021b48625.  I set up my brand-new Atom 1.17.0
> according to those instructions.
>
> I am not sure this question has anything to do with Proto-Repl, except
> that Proto-Repl motivated the experiment.
>
>  1. Open empty file b.clj amidst a Clojure project.  Now the mode line
> says "Parinfer:Indent LF UTF-8 Clojure (λ) strict"; the λ is green and
> "strict" is lighter gray.
>
>  2. Type
> (when true (println "cow
> and the outcome is
> (when true (println "cow"))
> which is very nice.
>
>  3. Desire to reformat the form on two lines
>
>  3. Position cursor before the (println
>
>  4. Press Enter
>
>  5. Result:
> (when true)
> (println "cow")
>
> It has changed the meaning of the program!  By the way, this is different
> from what happens in the parinfer demo (http://shaunlebron.github.io/
> parinfer/demo).  There, the result of the same keystrokes is
>
> (when true
>   (println "cow"))
>
> Anyway, proceed:
>
>  6. Try to restore the working state of the program with ^Z to undo:
>
> Result:
>
> (when true)(println "cow")
>
> But that is not something I ever had.
>
> Is this all working as intended?  How do people keep parentheses from
> rebelling into nonsense in Atom?
>
> --
> 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.
>



-- 
James Reeves
booleanknot.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.


Re: Looking for help creating this function/macro

2017-05-18 Thread James Reeves
I'd first factor out all the parts you can into a function. So for instance:

(defn html-spec [html-tag]
  (s/or :map(st-ds/spec html-tag {:tag (tag html-tag)})
:vector (s/cat :tag (tag html-tag

This will allow you to write:

(s/def ::a (html-spec ::a))

I'd be inclined to leave it there, but if you really want to use a macro,
we could write:

(defmacro def-html-spec [html-tag]
  `(s/def ~html-tag (html-spec ~html-tag)))

Notice that the macro starts with "def". This is a good indicator for
anyone using it that this is a macro that defines something.

On 18 May 2017 at 17:23, david swift <masterdavidsw...@gmail.com> wrote:

> I forgot to mention I am using the following library https://github.com/
> metosin/spec-tools; where you see (st-ds/spec) calls is the use of that
> library.
>
>
> On Thursday, 18 May 2017 17:21:45 UTC+1, david swift wrote:
>>
>> Hey Guys,
>>
>> I am looking for help creating a particular function/macro, right now
>> I've no experience using macro's and I'm under the impression it might be
>> the right solution to my problem, that produces a spec output but a very
>> specific spec output. My goal here is to reduce the constant repeating of
>> the same spec over and over with only the tag portion being the part that
>> changes.
>>
>> this is a little helper function I've been using to reduce repeating
>> (defn- tag [tag] (s/and keyword? #{tag}))
>>
>> this is the core of what I need help with, this is currently what I have
>> and find it not to work, even in macro form but that's most likely down to
>> my poor knowledge of macro's.
>> (defn html-spec-creator [html-tag]
>>(s/def html-tag
>>  (s/or
>>  :map (st-ds/spec html-tag {:tag (tag html-tag)})
>>  :vector (s/cat :tag (tag html-tag)
>>
>>
>> (html-spec-creator ::a)
>>
>> the intended output of the above is to produce the following
>> (s/def ::a (s/or :map (st-ds/spec ::a {:tag (tag :a)}) :vector (s/cat :tag
>> (tag :a
>>
>> --
> 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.
>



-- 
James Reeves
booleanknot.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.


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

2017-04-10 Thread James Reeves
Using the preset infinity constants is probably the best solution in this
case. :)

- James

On 11 April 2017 at 01:50, Brian Beckman  wrote:

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

-- 
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 James Reeves
I think what you have is overly complex for what you want to do.

Consider this alternative spec:

  (s/def ::virtual-time
(s/or :number number?, :limit #{::infinity- ::infinity+}))

Then we write a comparator:

  (defn compare-times [a b]
(cond
  (= a b) 0
  (= a ::infinity+) +1
  (= a ::infinity-) -1
  (= b ::infinity+) -1
  (= b ::infinity-) +1
  :else (compare a b)))

>From there we can derive less-than and greater-than functions if we really
need them.

I don't think you need protocols, records or custom generators.

- James

On 10 April 2017 at 17:30, Brian Beckman  wrote:

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

Re: Atom in macros ==> Can't embed object in code

2017-04-07 Thread James Reeves
Why don't you put the "let" that defines the atom counter inside the quoted
form?

- James

On 7 April 2017 at 22:21, Max Muranov  wrote:

> I need to create logger for machine learning debugging. First, I wanted to
> perform this string:
>
> (create-logger 10 "Epoch #" :epoch ", Error: " :error)
>
> This code will cause this output while training:
>
> Epoch #10, Error: 2.0
> Epoch #20, Error: 1.0
> Epoch #30, Error: 0.0
> Epoch #40, Error: 0.0
> ...
>
> I wrote this code:
>
> ;; Training logging
>
> (defmulti resolve-logger-keyword (fn [kwd] kwd))
>
> (defmethod resolve-logger-keyword :epoch [_]
>   (fn [trainer] (.getIteration trainer)))
>
> (defmethod resolve-logger-keyword :error [_]
>   (fn [trainer] (.getError trainer)))
>
> (defmacro create-log-func [args]
>   `(fn [trainer#]
>  (for [arg# ~args]
>(if (keyword? arg#)
>  ((resolve-logger-keyword arg#) trainer#)
>  arg#
>
> (defn create-logger [each-n-messages & args]
>   (let [counter (atom 0)
> logger-message (create-log-func args)]
> (fn [trainer]
>   (swap! counter inc)
>   (when (<= each-n-messages @counter)
> (swap! counter (fn [_] 0))
> (println (apply str (logger-message trainer)))
>
>
> This code works fine. But now I want this line be possible:
>
> (create-logger 10 "Epoch #" :epoch ", Error: " (* :error -1))
>
>
> In other words, I want to perform operations over this logger parameters.
> It's inside of the logger, so at first I need to make macro create-logger
> instead of function.
> I try to write this:
>
> (defmacro create-logger [each-n-messages & args]
>   (let [counter# (atom 0)
> logger-message (create-log-func args)]
> `(fn [trainer#]
>   (swap! ~counter# inc)
>  ;   These lines are not important yet
>  ; (when (<= ~each-n-messages @~counter)
>  ;   (swap! ~counter (fn [_] 0))
>  ;   (println (apply str (~logger-message trainer#)))
>
> And after trying to execute the first line:
>
> (create-logger 10 "Epoch #" :epoch ", Error: " :error)
>
> I get the error:
>
> clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Can't
> embed object in code, maybe print-dup not defined:
> clojure.lang.Atom@501e8e4f, compiling:(D:\Programming\
> Clojure\Projects\trade-ai-server\src\trade_ai_server\ai_trader.clj:97:1)
>
>
>
>
>
>
> --
> 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] irresponsible/codependence 0.1.0 (dependency resolution for apps - a twist on integrant)

2017-03-20 Thread James Reeves
Nice work. The use of keys is interesting.

I'm not sure of this affects Codependence, but I released a new version of
Integrant a few days ago that supports multiple components of the same type
via composite keys.

- James

On 19 March 2017 at 09:17, James Laver  wrote:

> Hi all,
>
> The Irresponsible Clojure Guild is pleased to announce codependence 0.1.0
> is now available on clojars.
>
> This library came about because I liked integrant, but I wanted a bit more
> flexibility. It's built upon integrant (which is cool, I ported it to
> clojurescript!) but with a twist.
>
> In ordinary integrant, you might specify an app like this (component
> configs elided for brevity):
>
> ```
> {:http {}
>  :db {}}
> ```
>
> In codependence you specify them like this:
>
> ```
> {:http {:co/tag :http/aleph}
>  :db {:co/tag :db/utrecht}
> ```
>
> In the first example, :http and :db are the tags one will register
> behaviour for. in the second, they are :http/aleph and :db/utrecht.
> integrant refs are unmodified
>
> This firstly means that one tag can instantiate multiple components of the
> same type and secondly makes it easier to ship predefined components and
> let a user stitch them together as config
>
> dep coord: [irresponsible/codependence "0.1.0"]
> github: https://github.com/irresponsible/codependence
>
> Cheers,
> James (and the ICG)
>
> --
> 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: Error in main using Stuart Sierra's Component when deploying to Heroku

2017-03-13 Thread James Reeves
Can you provide the full error message? So the cause as well as the
Component ex-info wrapper?

I don't think this is anything to do with :listener being nil. I think
you're looking at the Component exception and not checking the "cause"
exception with .getCause.

My guess is that you're running into problems at (env :port), which will be
a string, while the port in the edn configuration will probably be an
integer. So it works when PORT isn't set on your local machine, but fails
on Heroku where PORT is set.

- James

On 13 March 2017 at 16:38, 'Rickesh Bedia' via Clojure <
clojure@googlegroups.com> wrote:

> I am trying to start my clojure application on my heroku dyno but I keep
> getting and error in my stuartsierra.component/start.
>
> Below is my core file containing my main function.
>
> (defrecord Listener [listener]
>   component/Lifecycle
>   (start [component]
> (assoc component :listener (yada/listener
>  ["/"
>   [(view/view-route)
>routes/route-handler
>["public/" (new-directory-resource
> (io/file "target/cljsbuild/public") {})]
>[true (as-resource nil)]]]
>  (or (env :port) (get (read-config
> "resources/config.edn" {:profile :dev}) :webserver))
>  )))
>   (stop [component]
> (when-let [close (-> component :listener :close)]
>   (close))
> (assoc component :listener nil)))
>
> (defn new-system []
>   (component/system-map
> :listener (map->Listener {})
> ))
>
> (def system nil)
>
> (defn init []
>   (alter-var-root #'system
>   (constantly (new-system
>
> (defn start []
>   (alter-var-root #'system component/start))
>
> (defn stop []
>   (alter-var-root #'system
>   (fn [s] (when s (component/stop s)
>
> (defn go []
>   (init)
>   (start))
>
> (defn reset []
>   (stop)
>   (refresh :after 'web.core/go))
>
> (defn -main
>   [& [port]]
>   (component/start (new-system))
>   (println "System Started")
>   @(promise))
>
> This is my core file with all my stuartsierra.component code. This all
> works perfectly when I run it locally on my laptop doing lein repl and then
> (go) and also when I just do lein run. So I am confused as to why it
> doesn't work when I push this to the heroku dyno.
>
> The error I get is
>
> Exception in thread "main" clojure.lang.ExceptionInfo: Error in component
> :listener in system com.stuartsierra.component.SystemMap calling
> #'com.stuartsierra.component/start {:reason :com.stuartsierra.component/
> component-function-threw-exception, :function
> #'com.stuartsierra.component/start, :system-key :listener, :component
> #web.core.Listener{:listener nil}, :system #},
> compiling:(/tmp/form-init9049917434081554913.clj:1:73)
> This is telling me that my :listener is nil in the system-map. When I
> check locally (doing lein repl (go)) in (keys system) is (:listener) which
> is good so that means that the listener is starting and is in the system.
>
> When I do (-> system :listener) I get #web.core.Listener{:listener {:port
> 3300, :close #object[yada.aleph$listener$fn__21671 0xa5d4865
> "yada.aleph$listener$fn__21671@a5d4865"], :server
> #object[aleph.netty$start_server$reify__13574 0x3cc9a232
> "aleph.netty$start_server$reify__13574@3cc9a232"]}} which is perfect as
> the port has loaded up (3300) and the server has started.
>
> This makes it all the more confusing as to why the :listener is nil in my
> heroku app
>
> Any help would be much appreciated. Thanks
>
> --
> 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 

Re: How can I re-order rows in a table (hiccup)?

2017-02-24 Thread James Reeves
Generally you'd approach the problem by using an intermediate structure.
For example:

  (def data
{:headers [:color :size]
 :rows[{:color "blue",  :size 4}
   {:color "red",   :size 2}
   {:color "green", :size 7}])

Then you could build a function that translates this data structure into a
Hiccup table:

  (defn ->table [{:keys [headers rows]}]
[:table
 [:tr (for [h headers] [:th (str/capitalize h)])]
 (for [row rows]
   [:tr (for [h headers, :let [v (row h)] [:td h])])])

Then you could write something like:

  (->table (update data :rows (partial sort-by :color))

- James

On 24 February 2017 at 22:41, John Gabriele  wrote:

> I'm using hiccup, and I'd like to build a table, but then have the option
> to re-order it (sort its rows by a column of my choosing). I want a
> `sort-table-by` function.
>
> That is, if I've got
>
>
> Color   Size
> --  
> red 2
> green   7
> blue4
>
>
> (or, as a data structure: `(def tbl [:table [:tr [:th "Color"] [:th
> "Size"]] [:tr [:td "red"] [:td 2]] [:tr [:td "green"] [:td 7]] [:tr [:td
> "blue"] [:td 4]]])`)
>
> I'd like to be able to do `(sort-table-by tbl 0)` and get
>
>
> Color   Size
> --  
> blue4
> green   7
> red 2
>
>
> or `(sort-table-by tbl 1)` and get
>
>
> Color   Size
> --  
> red 2
> blue4
> green   7
>
>
> Where it gets tricky though is when your table has various attribute maps
> in it, and also when some of the values you're sorting on may be links.
>
> A first try at a solution yields ... oh man, {sigh, deep breath} this,
> which doesn't work:
> .
>
> Thanks!
> -- John
>
> --
> 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: how to send SSL certificate in POST request?

2017-02-21 Thread James Reeves
There's an article here that might be useful to you:

https://www.lvh.io/posts/https-requests-with-client-certificates-in-clojure.html

With clj-http, you have to use a Java keystore. I wrote a library a few
years ago for importing certificates into keystores in Clojure, though I'm
not sure how well it works now. Otherwise you can use the normal Java
process.

https://github.com/weavejester/crypto-keystore

- James

On 21 February 2017 at 23:36, Pierre Masci  wrote:

> Hi, I am new to Clojure and using clj-http for the first time, to
> implement a REST client.
> I don't find anywhere how to indicate where my SSL certificate is located.
> Here is what I did:
>
> (ns my-client.core
>   (:require [clj-http.client :as client]
> [clojure.pprint :refer :all]))
>
> (def my-appkey "...")
>
> (defn login [username password appkey]
>   (client/post "https://.../api/certlogin;
>{:headers {"X-Application" appkey
>   "Content-Type" 
> "application/x-www-form-urlencoded"}
> :form-params {"username" username "password" password}}))
>
> (defn -main []
>   (pprint (login "..." "..." my-appkey)))
>
>
> This sends me back a response which indicates that I need to send the SSL
> certificate.
> When I send the same request with curl and indicate the certificates, it
> works. This is the successful curl request:
>
> curl -q -k --cert client-2048.crt --key client-2048.key 
> https://.../api/certlogin
> -d "username=...=..." -H "X-Application: ..."
>
>
>
> --
> 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: A problem about position of function used by binding

2017-02-06 Thread James Reeves
When you define test4 in your first example, the compiler doesn't know that
test1 is dynamic, so it'll optimise out the var for performance.

To fix it, ensure that the var is declared as dynamic:

  (declare ^:dynamic test1)

- James

On 7 February 2017 at 03:26, guid  wrote:

> hello everyone
>
> I have a problem about binding function in clojure1.8.
> when I changed position of function which call a bound function I got
> different result.
>
> If I define test4 (call test1 within it) before test1, binding would not
> work
>
> (declare test1)
>
> (defn test2 [](prn "test2"))
>
>
> (defn test4 [] (test1))
>
>
> (defn ^:dynamic test1 [] (prn "dynamic test1"))
>
>
> (defn testB []
>   (binding [test1 test2]
> (test1)
> (test4)
> ))
>
>
> when I call (testB) result is
>
> "test2"
> "dynamic test1"
>
>
> But if I change postion of (defn test4 xxx) and (defn ^:dynamic test1 ), 
> binding will work well.
>
>
> (declare test1)
>
> (defn test2 [](prn "test2"))
>
>
> (defn ^:dynamic test1 [] (prn "dynamic test1"))
>
>
> (defn test4 [] (test1))
>
>
> (defn testB []
>
>   (binding [test1 test2]
> (test1)
> (test4)
> ))
>
>
> result is
>
> "test2"
> "test2"
>
>
> Any way, with-bindings is the same as binding, but why ?
>
>
> 
>
> any help would be appreciated
>
> --
> 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: newbie trying to mod a clojure based game

2017-01-29 Thread James Reeves
If you have Leiningen installed, then run:

lein cljsbuild once

The compiled Javascript will be in target/app.js

Admittedly this isn't very obvious to beginners unless you happen to guess
what the cljsbuild plugin does.

- James

On 29 January 2017 at 23:45, James Thorne  wrote:

> I'm trying to mod a game called epitaph from github
> https://github.com/mkremins/epitaph
>
> The cljs files inside the src are easy enough to understand and I
> foolishly thought modding those were all that was needed.
> I signed up to github, forked and modded, found out this task was not so
> simple, abandoned the github and moved the modded files to my pc (when I
> figure this out I'll return to github)
> I now understand those files need to be compiled into javascript which is
> what the index file actually uses, part of the AOT compiling.
> I did the quickstart https://github.com/clojure/
> clojurescript/wiki/Quick-Start and figured out how to compile something
> basic,
> However since this was done in leiningen, I had to install that but still
> don't know how to compile using that (the tutorial talks about how to build
> a project.clj file but not how to actually use one for AOT compiling).
> I still don't know how to get the epitaph project.clj file to do it's
> thing and compile the pretty src files into ugly javascript
>
> So if anyone here is kind enough to help a utter novice out by showing how
> to use leiningen to compile the files for the epitaph game I would be very
> happy.
>
> --
> 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] Hiccup 2.0.0-alpha1

2017-01-14 Thread James Reeves
I'd like to tentatively announce the first alpha version of Hiccup 2.0.0.

This release introduces automatically escaping of strings, which has been a
frequently requested feature. Hiccup 1.0 had no way of distinguishing
between a string of text and a fragment of HTML, so for version 2.0 a new
type has been introduced to represent the latter.

A lot of projects depend upon Hiccup, and after thinking about it for a
while, and watching Rich's Spec-ulation
 talk, I decided to introduce
a new namespace rather than break backward compatibility. So although
Hiccup 2.0.0 is a major version change, it should be backward compatible
with version 1.0.

The new namespace is hiccup2.core, and it works like this:

  (require '[hiccup2.core :refer [html raw]])

  (str (html [:span "one < two"]))
  ;=> "one  two"

Notice that now strings are escaped by default, but we also need to
explicitly convert the HTML fragment into a string by using clojure.core/str
.

By using a compiled intermediate format, we gain a lot more potential
flexibility. For example, possible future feature currently under
consideration is to support different ways of formatting the HTML. Using an
intermediate format allows us to do this after pre-compilation has taken
place.

Because this is an alpha release, the hiccup2.core namespace is not set in
stone, but it does seem to be the simplest solution to the problem of
incompatibility. Suggestions for better ways to solve this are welcome and
encouraged.

As well as escaping strings, additional syntax sugar for attributes has
been introduced. This should be familiar to anyone using Reagent:

  (str (html [:span {:class ["foo" "bar"]} "example"]))
  ;=> "example"

  (str (html [:span {:style {:color "red"}} "example"]))
  ;=> "example"

Please give the alpha release a spin, and if there are any
incompatibilities please let me know.

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


[ANN] Ring 1.5.1 released to fix path traversal vulnerability

2017-01-10 Thread James Reeves
There is a path traversal vulnerability in Ring that affects applications
that serve resources from the filesystem. It does not affect Ring sites
deployed as uberjars.

Versions affected: Every version prior to 1.5.1; 1.6.0-beta1 to 1.6.0-beta6

Fixed versions: 1.5.1, 1.6.0-beta7

Link: https://github.com/ring-clojure/ring

*Overview*

This vulnerability is caused by a bug in the
ring.util.response/resource-response function. An attacker can use this
vulnerability to access files that are in a directory on the classpath, but
they cannot access resources contained in a jar.

This also affects the ring.middleware.resource/wrap-resource middleware,
and the compojure.route/resources function.

*Example*

Consider a minimal Compojure application:

(ns example.core
  (:require [compojure.core :refer :all]
[compojure.route :as route]))

(defroutes app
  (GET "/" [] "Hello World")
  (route/resources "/")
  (route/not-found "Not Found"))

Assume that this isn't packaged as an jar when deployed, but is deployed as
a directory of source files. An attacker can craft a URL to read any file
on the classpath that is not in a jar:

curl -vvv --path-as-is 'http://localhost:3000//../example/core.clj'

*Cause*

Unlike the file-response function, the resource-response function did not
properly santize the path from the client.

*Fix*

The resource-response function now checks for path segments containing
"..", and also ensures that for file-based resources, the canonical
filepath of the resource must be contained within the canonical filepath of
the :root option.

This fix means that Ring will not follow symlinks on the classpath if they
lead to files or directories outside the path specified in the :root option.
If you happen to need this for any reason, then you need to set the
:allow-symlinks? option to true.

*Recommendation*

Upgrade to 1.5.1 as soon as possible.

*Credit*

Thanks go Tim McCormack for discovering this vulnerability, and his
responsible disclosure of it. Thanks also go to Dmitri Sotnikov for
reviewing the fix.

-- 
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: The Expires field in cookies has failed pre-assert.

2017-01-08 Thread James Reeves
On 9 January 2017 at 03:43, 松舘剛志  wrote:

> I hope to think so too, but I don't know what will happen when remove
> cookie...
>

What's the purpose of your code?

Your code takes a response from the Twitter API, and then attempts to proxy
it. But why?

If we knew what you are trying to accomplish, it might be easier to help
you.

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


Re: The Expires field in cookies has failed pre-assert.

2017-01-08 Thread James Reeves
On 9 January 2017 at 02:37, 松舘剛志  wrote:

> Hi, James.
> Thank you for response.
>
> I've understood clj-http response and ring response are not identical.
> I hope to know way to respond cookies via Twitter as valid one.
> Would you know way to respond it?
>

Why do you want cookies from Twitter's API in the first place? Aren't the
cookies irrelevant in this case?

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


Re: The Expires field in cookies has failed pre-assert.

2017-01-08 Thread James Reeves
To add some background to this: the author reported this as an issue on
Ring. They appear to be trying to turn clj-http response into a Ring
response, so this isn't anything directly to do with cookies. The problem
is that clj-http responses are similar but not identical to Ring responses.

Perhaps the author could explain what they're trying to do?

- James

On 8 January 2017 at 14:00, 松舘剛志  wrote:

> For example,
>
>
> When call some Twitter APIs:
>
>
> (ns foo
>   (:require [clj-http.client :as http]
> [ring.util.response :as ring])
>   (:import [clojure.lang ExceptionInfo]))
>
> (try
>   (let [response (http/post "https://api.twitter.com/1.1/statuses/show.json;)]
> #_"Something to do."
> (ring/status response 200))
>   (catch ExceptionInfo e
> #_"Something to do."))
>
> In any case, this will return AssertionError.
>
>
> ERROR in (statuses-show-test) (cookies.clj:73)
>>
> Uncaught exception, not in assertion. expected: nil actual:
> java.lang.AssertionError: Assert failed: (every? valid-attr? attrs)
> Fllowing some stacktraces...
>
>
> This has been failed pre-assert for ring.middleware.cookies/write-attr-map 
> because the Expires field in cookies via Twitter is not RFC822. Its format is 
> EEE, dd-MMM- HH:mm:ss z (in US locale). How should I do for responding 
> via Twitter APIs with valid Expires?
>
> --
> 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: Kotlin null-safety in Clojure?

2016-12-30 Thread James Reeves
Well, if you use Typed Clojure you get static null checking. Clojure spec
can give you dynamic null checking you can turn on during development and
turn off during production. There's also Spectrum, which statically checks
Clojure spec, but obviously it can't handle all eventualities.

- James


On 30 Dec 2016 8:53 p.m., "gvim" <gvi...@gmail.com> wrote:

On 30/12/2016 19:19, James Reeves wrote:

> Well, Kotlin is statically typed, and Clojure is dynamically typed. Null
> checking on dynamically typed languages is hard (impossible?) to achieve
> without impacting performance.
>
> - James
>
>
Personally, I'd trade the whole of clojure.spec & core.typed for this
feature of Kotlin.


gvim

-- 
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: Kotlin null-safety in Clojure?

2016-12-30 Thread James Reeves
Well, Kotlin is statically typed, and Clojure is dynamically typed. Null
checking on dynamically typed languages is hard (impossible?) to achieve
without impacting performance.

- James

On 30 December 2016 at 17:59, gvim  wrote:

> What would it take to implement Kotlin's null-safety in Clojure? Are there
> any Clojure-specific gotchas which make it more difficult than in Kotlin?
>
> gvim
>
> --
> 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: Why does "clojure.core/run!" end in an exclamation mark?

2016-12-25 Thread James Reeves
On 25 December 2016 at 10:30, Paulus Esterhazy  wrote:

> The following fn names in clojure.core contain an exclamation mark:
>
> "vswap!" "vreset!" "set-error-mode!" "set-agent-send-executor!"
> "disj!" "conj!" "pop!" "compare-and-set!" "reset-meta!"
> "set-error-handler!" "set-agent-send-off-executor!" "dissoc!" "assoc!"
> "reset!" "alter-meta!" "persistent!" "run!" "set-validator!" "swap!"
> "volatile!" "io!"
>
> What these functions have in common is that they do something
> side-effectful, i.e. they do something over and above returning a
> value.


Well, yes, but they're also unsafe to run in an STM transaction, except
potentially for run!.

I think that's the convention followed by many in the
> community, although it's not a perfect convention -- there are many
> side-effecting functions in core without exclamation marks (print,
> require, ns-unmap).
>

require and ns-unmap are side-effecting, but idempotent, meaning that
they're safe to run in a transaction.

Functions that reference I/O like print or slurp are of course obviously
unsafe, and in those cases maybe an exclamation mark was considered
redundant.

But I guess the answer is that there's no fixed convention for ending a
function with an exclamation mark. The Clojure Style Guide suggests
exclamation marks should be for functions that are unsafe to use in STM
transactions, and I thought that stemmed from their usage in clojure.core,
but maybe the meaning is much looser than that.

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


Why does "clojure.core/run!" end in an exclamation mark?

2016-12-24 Thread James Reeves
My understanding is that the convention used in clojure.core is to put an
exclamation mark onto the end of any function unsafe to run in a
transaction.

Does the reasoning differ for "run!" or is it assumed that the function
passed to "run!" will not usually be idempotent?

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


Re: Stack Overflow Question

2016-12-24 Thread James Reeves
On 24 December 2016 at 11:48, Jiacai Liu  wrote:

> how to make correct fn args when create fn using macro
> http://stackoverflow.com/q/41312963/2163429?sem=2
>

For reference, I posted an answer on StackOverflow.

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


Re: POST in Ajax - Invalid anti-forgery token

2016-12-23 Thread James Reeves
Another way of introducing the anti-forgery token is to bind it to a
javascript variable.

  [:script "var antiForgeryToken = " (pr-str *anti-forgery-token*)]

In ClojureScript, you can then access the token with js/antiForgeryToken.

The Ring-Defaults library exists to provide a way of applying common
middleware in the right order. Certain middleware depend on other
middleware, so the order in which they're applied to a handler is
important. For instance, wrap-anti-forgery depends on wrap-session.

The wrap-defaults middleware just takes a map of options, and then uses
this to decide which middleware to apply. The order in which the middleware
is applied it handled for you. It also provides some default maps of
options that you can adapt.

Regarding *anti-forgery-token* being unbound, this is because it's a
binding. If a var has "earmuffs", like *foo*, it indicates it's designed to
be used with the binding macro. For example:

  (declare *foo*)   ;; like def, but doesn't have a value yet

  (defn print-foo []
(println *foo*))

  (binding [*foo* "Hello World"]
(print-foo));; prints "Hello World"

The value of *foo* is passed into print-foo without needing to be passed as
an argument. Any function inside the binding can access *foo*.

This is useful property for *anti-forgery-token* to have, because it means
we don't need to manually pass the token to the function that returns the
response.

The anti-forgery token is randomly generated for each request you make,
then added to both the session (automatically) and the page you return as a
response (manually). The idea is that this ensures two things:

1. The user is logged in
2. The user has come from a page you control

You mention that Clojure rewards investment into its fundamental building
blocks. That's very true, and at this point unfortunately a little
unavoidable! Fortunately the building blocks are fairly simple IMO, and
once you understand them you should make more rapid progress.

Also, don't be afraid of looking at source code. Clojure libraries are
frequently both small and "flat". You don't get the dense hierarchies of
class structures that tend to occur in OOP.

When I was using Ruby and Python it was extremely rare for me to look at
the source code of libraries, for exactly the reason you mention. But in
Clojure I almost always look at the source code of any library I use. Some
are still complex, but most I find to be understandable even if I'm just
skimming.

Clojure web development is currently made up of small, specialised
libraries. I think overall it's easier for me to understand what's going on
in Clojure as opposed to something like Ruby. On the other hand, because
the pieces are isolated, tasks like CSRF-protection that require
coordination between the server and the client become difficult.

Arachne  is a promising attempt to make a
web framework for Clojure. Another project that's slowly heading in that
direction is my own Duct  project,
though by smaller increments. I know Luke expects an alpha of Arachne out
by the end of January, and the next version of Duct should be out at around
the same time.

- James


On 23 December 2016 at 16:49, Seth Archambault  wrote:

> Okay, armed with the new clarity, I felt embolden to tackle this once
> more. Here's the next steps for those trying to tack CSRF protection onto a
> Reagent project created with lein new reagent.
>
> In handler.clj - you'll add the ring.middleware.anti-forgery and refer to
> *anti-forgery-token*
>
> (ns myapp.handler
>   (:require
> [ring.middleware.anti-forgery :refer [*anti-forgery-token*]]))
>
>
> Then, lower down in your code you'll have something like this:
>
> (html5
>   [:head
>[:meta {:csrf-token *anti-forgery-token*}]
>
>
> This will create a token for you.
>
> Now I haven't gone the rest of the distance with this problem so I can't
> say that it's all downhill from here, it's possible I'm messing up and
> re-generating a token that won't match what's already matched in the
> session. Let me know if that's what I'm doing :(
>
> But the next thing I would do, is in /cljs/myapp/core.cljs - I would find
> a way to pull in this token from the meta tag (maybe by using vanilla
> javascript) and then add it to my post commands.
>
> A couple things that confused me:
>
> It's not obvious that you have to add ring.middleware.anti-forgery to
> handler.clj, because in the examples in the documentation we're pulling
> that in so we can do "wrap-anti-forgery" in our middleware.clj. However,
> this is done automatically using ring.middleware.defaults, in the
> middleware.clj file, so it looks like ring.middleware.anti-forgery
> doesn't need to be anywhere.
>
> However, without ring.middleware.anti-forgery, it seems
> *anti-forgery-token* isn't bound.. once you require that, that it exists!
>
> Let me know if my assumptions are wrong on this - it's possible 

  1   2   3   4   5   6   7   8   9   10   >