Re: [ANN] Discontinuing 4clojure.com

2021-07-10 Thread Didier
I'm guessing this also means the Android App will no longer work for it?

On Tuesday, July 6, 2021 at 12:12:21 p.m. UTC-7 Robert P. Levy wrote:

> Just wanted to correct a mistake in what I wrote above. Obviously you 
> can't clear the password hashes while retaining a link between people and 
> their accounts, so it would more accurately be stated as all accounts are 
> gone and you have to create a new account.
>
> On Tue, Jul 6, 2021 at 12:42 AM Robert Levy  wrote:
>
>> Hi Alan,
>>
>> Just as a thought.  If it's minimal work on your end (eg. if the folks 
>> from Roam research who chimed in above pick it up) why not clear the 
>> password hashes and let the new maintainer handle the communication that 
>> passwords need to be reset?
>>
>> Rob
>>
>> On Sun, Jul 4, 2021 at 1:26 PM Alan Malloy  wrote:
>>
>>> TL;DR: Turning off 4clojure.com by the end of July 2021
>>>
>>> Hello, 4clojure problem solvers. You've probably noticed SSL errors on 
>>> 4clojure.com over the last week. The old decrepit system 4clojure runs 
>>> on has finally gotten out of date enough that I can't even figure out how 
>>> to get it recent enough that SSL certs will auto-renew anymore.
>>>
>>> In principle I could start from scratch on a new server and move 
>>> 4clojure over, but I won't. 4clojure has been piggybacking along on a 
>>> server that I use for personal reasons, and over the years I have less and 
>>> less reason to keep paying for that server - it's now pretty much just 
>>> 4clojure costing me an embarrassing amount of money every month because I 
>>> haven't wanted to disappoint the community by shutting it down. This SSL 
>>> thing is just what made me finally pull the trigger.
>>>
>>> I don't have a specific EOL date in mind, but sometime near the end of 
>>> the month, since that's the billing cycle. Until that time, 4clojure still 
>>> works, as long as you don't mind clicking through the security warnings - 
>>> it really is still me hosting the site, and since the connection is still 
>>> HTTPS (albeit with an invalid cert) I think that means your data is still 
>>> safe. If you have solutions to problems you're proud of, you've still got 
>>> some time to print them out and put them up on your refrigerator.
>>>
>>> I'm not seeking new maintainers. I'd feel uncomfortable handing over a 
>>> database with so many email addresses and password hashes in it to anyone. 
>>> The service has had a good run - just over a decade since the first 
>>> release 
>>> .
>>>  
>>> I hope you enjoyed it during that time.
>>>
>>> -- 
>>> 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/385cdef8-fa40-47ba-b5b1-0b3a7cc34935n%40googlegroups.com
>>>  
>>> 
>>> .
>>>
>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojure/3c3b7835-ab72-4354-8bfa-71eca12d2e0en%40googlegroups.com.


Re: Frustrations so far

2016-09-04 Thread Didier
*1) Slow startup speed.*

Everyone dislikes the slow startup speed. Though it's been argued that it 
should be known as the Clojure slow startup speed. Since even though the 
JVM is slower to start then say python, most of the slowness comes from the 
Clojure overhead.

*I know this problem is being addressed by the Clojure supporters, but its 
a hard one to solve, all I can say is that its improved version after 
version.*

*2) Slow dependency resolution*

It doesn't sound like an issue with Clojure. Can you elaborate? Are you 
complaining about Leiningen being slow, or just that having to download 
dependencies is slow? Either way, this is probably more of a JVM issue, or 
even a tooling issue, you could look into alternate tooling.

*Not a Clojure related problem.*

*3) `empty?` doesn't behave as I intuitively interpret the name of it*

One thing you should embrace in Clojure, is that part of why its so awesome 
is that you are not as restricted by the limitations of the language as 
with other languages. So if you don't like empty? throwing exceptions for 
Long and Keyword, you can re-def your own empty? which catches those and 
returns false or true (whatever behavior you want) instead.

As some people have said before, a lot of the functions have good reason to 
behave as they do, but sometimes its not as intuitive from the name or form 
people's expectations. The doc mentions: "Returns true if coll has no items 
- same as (not (seq coll)). Please use the idiom (seq x) rather than (not 
(empty? x))" I'd be curious if anyone knows what is the idea behind empty? 
and why the doc mentions to use the idiom (seq x) when there is also a 
not-empty fn in core.

As an example, I struggled with `contains?` for a while. Couldn't figure 
out why they decided to make this: `(contains? [:a :b :c] :a)` return 
false. Why they chose to make contains? check for the existence of the 
index on a vector. Then I learned that the use-case behind `contains?` is 
to verify that a call to `get` will succeed. Once I learned that I was 
like... make total sense. So I wrote myself a `contains-val?` for the 
use-case I was having and done. I'm sure there's similar reasoning for 
`empty?`

*So I'd say this is not a Clojure related problem, though maybe there's a 
little issue with the names of functions having similar names then other 
popular languages and not behaving the same way.*

*4) Maps are unordered by default*

Maps are unordered from the theory itself. Don't ever expect Maps to be 
ordered, unless its very explicitly stated. Ordered Maps have different 
time/space characteristics too, which is why Maps are unordered by default. 
This isn't anything to do with Clojure. You should try and get more 
familiar with the formal literature on common data structures, as its what 
most languages build upon.

*Not a Clojure related problem.*

*5) Reloading has some quirks*

Clojure gives you so much reloading-ability with its REPL centric 
development process, that it plays against it when it fails, we get really 
upset. Its almost like the uncanny valley of reloading. You can search for 
reloaded workflows though, some people have apparently figured out ways to 
organize your code so that everything can be reloaded without ever failing 
or having to restart the REPL.

*This problem relates to Clojure, but also to Lisp in general, and I don't 
think its solvable without constraining the language too much.*

*6) Cryptic official doc*

I thought the official doc was very cryptic at first too, but over time, I 
got used to the way its documented, and I can now figure out how to use 
almost all functions just from the official doc. So I'd say this is just a 
matter of time and experience with the nomenclature and the way its 
explained. But I agree, its not meant for people just starting off with 
Clojure. I recommend clojuredocs for a more beginner friendly doc.

*Clojure could try to add a bit of a friendlier doc to its official doc.*

On Wednesday, 20 July 2016 05:54:27 UTC-7, Peter Romfeld wrote:
>
> I really love clojure over all, it makes maintenance/collaboration of code 
> such a breeze. its easy to get new employees start to work on it even 
> without any previous clojure knowledge!
>
> I do hate the JVM startup shit, i hate how you it takes forever to fetch 
> deps on a aws medium instance (you probably can fix it with uberjars)
> Im frustrated with `empty?` throwing exceptions for Long and Keyword
> Not complete clojure, but i hate datomic.api/log since you cant put into 
> your tests with a in-mem db
> I had some issues understanding that maps of certain size are not in order 
> anymore because of the underlying java functions and optimizations 
> Im a bit upset about development reload with defrecords
> most of the things that are not documented by the community are documented 
> very cryptic and hard to understand
> the api docs are almost useless! - to get the arrity and stuff.. wtf i 
> still have no clue how to use 

Java like static typing for Clojure?

2016-10-15 Thread Didier
I know a lot of people like to say how unhelpful Java like static typing 
is, and only more powerful type systems of the ML family add value, but 
I've been wondering recently if for Clojure it wouldn't make more sense to 
simply extend the type hints to enable an optional Java like static typing 
scheme.

It is my understanding that ML style static typing is incredibly difficult 
to add properly and without compromise to a dynamic language. That doing so 
limits the scope of type inference, rendering the task of adding type info 
more tedious then in ML languages themselves.

ML style static typing provide enhanced safety grantees, but seem to add 
too much complexity to Clojure to be practical. What about a Java like 
static typing scheme though?

I haven't found in practice that the safety of Clojure was an issue, as the 
REPL workflow tend to promote quite a lot of testing. So I'm not too 
worried about needing the state of the art of provable correctness for my 
programs. What has been a biggest cause of issue to me was refactoring and 
shared code base across a team. Those last two use cases are actually 
pretty well handled by Java like static type checking. Is it a powerful 
type checker, not really, but it enables most trivial type errors to be 
caught early, and it allows easier integration points for other devs to 
follow, as well as documentation for functions, better tools support and 
easier refactoring, while also enabling performance optimizations.

I have limited knowledge in typing systems, and have no idea how easy it is 
to implement them, but as a user of Clojure, I feel like I would find an 
optional Java like static typing a great addition, one that I am more 
willing to use and benefit from then Typed Clojure's more complex ML style 
type checking.

What do other think?
Can anyone with better knowledge tell me if this would be feasible or if 
adding such gradual typing system is effectively as hard as adding ML style 
type checking?

-- 
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] Nightlight, an embedded editor for Clojure

2016-11-05 Thread Didier
Wow, this looks awesome.

For now, I'm pretty satisfied with Atom + ProtoREPL. But if your approach 
can achieve much better code completion, much better linting, much better 
refactoring and hopefully much better debugging, I'm going to have to move 
to it.

Actually, it would be awesome if you could try to focus on Debugging, 
because that part I feel is badly served by other Clojure IDEs. It would be 
great if I could use whatever editor I wanted, and if suddenly I needed to 
debug Clojure, I could drop Nightcode as a dependency and get a full 
fledged web browser based debugger.

On Saturday, 29 October 2016 16:50:37 UTC-7, Zach Oakes wrote:
>
> Yep I definitely plan on adding that feature. For now, you'll just have to 
> refresh your browser =) By the way, I just released version 1.1.0, which 
> adds some initial support for ClojureScript! I added a new section on the 
> website that explains how to set it up.
>
> On Saturday, October 29, 2016 at 3:41:05 AM UTC-4, ru wrote:
>>
>> Great work, Zach! Thank you. I would like to switch from 
>> Lifhttable+Terminal working environment that I use now, to Nightlight. But 
>> I definitely need "Refresh folder" and/or "Refresh file" actions, because 
>> sometimes I update source files from outside of a project. Is it possible 
>> to add something like that to Nightlight? 
>>
>> Sincerely,
>>  Ru
>>
>> воскресенье, 9 октября 2016 г., 5:03:58 UTC+3 пользователь Zach Oakes 
>> написал:
>>>
>>> Just when you thought I was done with my weird obsession with making 
>>> projects that start with “night”, I went and made another. This one is 
>>> called Nightlight, and it’s a Clojure editor with a unique twist: it is 
>>> meant to run *inside* your project, giving it direct access to the state of 
>>> your program. This might end up being a great idea, or an embarrassingly 
>>> stupid one.
>>>
>>> Website: https://sekao.net/nightlight/
>>>
>>> Github: https://github.com/oakes/Nightlight
>>>
>>> I’ve only been working on this for a few weeks. To explain the idea, 
>>> I’ll channel Uncle Bob and give it to you in the form of a socratic dialog 
>>> between myself (Z1) and myself from two weeks ago (Z2):
>>>
>>> Z2: Nightcode has a lot of crippling limitations. It has no code 
>>> completion, for starters. Its instaREPL is a toy, because it only works 
>>> with clojure core. Forget about refactoring support.
>>>
>>> Z1: It’s almost as if these are caused by the same core issue.
>>>
>>> Z2: Yeah almost. Anyway where was I...
>>>
>>> Z1: No, they actually are. Traditional editors and IDEs have the same 
>>> basic design -- they are standalone programs, so they have to use all sorts 
>>> of complicated maneuvers to understand your project. It’s a huge source of 
>>> complexity.
>>>
>>> Z2: What’s the alternative?
>>>
>>> Z1: Imagine completely reversing the relationship. Instead of an 
>>> external tool enveloping and running your program, what if your program ran 
>>> your development tool? What if they lived in the same process? Your editor 
>>> would have direct access to the state of your program, opening the doors to 
>>> all sorts of interactivity.
>>>
>>> Z2: So what’s the alternative?
>>>
>>> Z1: Are you serious? I just explained it.
>>>
>>> Z2: Right. Genius! Nobody has thought of this before.
>>>
>>> Z1: Plenty of people have, but for the most part those tools are not 
>>> mainstream. Various Lisp and Smalltalk tools blurred those lines. For 
>>> example, DrRacket can run your code in the same Racket instance that it is 
>>> running in.
>>>
>>> Z2: Doesn’t this mean if you crash your program, you crash your editor?
>>>
>>> Z1: Yeah...don’t do that.
>>>
>>> Z2: Got it. How do we build it? Should we just shoehorn Nightcode into 
>>> some kind of build task, so it pops up every time you start developing a 
>>> project?
>>>
>>> Z1: That would be pretty obnoxious, which I realize makes the idea more 
>>> appealing to you. But consider this: if it was a totally browser-based 
>>> editor, we could just run a little web server inside your project and the 
>>> user could interact with it via a browser.
>>>
>>> Z2: That sounds like a lot of work.
>>>
>>> Z1: Not really. Nightcode’s editor is already browser-based, so we just 
>>> need to make the rest of the interface. It should only take about a month, 
>>> or even less if a large hurricane happens to slam your city in the near 
>>> future, giving you nothing else to do but code and drink beer.
>>>
>>> Z2: Hah yeah that’s not going to happen.
>>>
>>

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

Re: Java like static typing for Clojure?

2016-11-05 Thread Didier
Spectrum (https://github.com/arohner/spectrum) seems quite interesting. I 
haven't tried spec yet, but form quick glance, it looks just as annoying as 
typed clojure to use.

I think I'm imagining something simpler though. Say a system that just used 
already existing Clojure type hints, and performed compile time checks 
about to whatever level is possible given the provided annotation.

So say I did:

(def ^int something "test")

This would fail at compile time.

Similarly:

(def ^String something "test")
(inc something)

It would fail at compile time.

Or:

(defn inc2 [^Long a]
  (inc (inc a)))
(inc2 1.80)

Would also fail.

And hopefully this:

(defn ^Long inc2 [^Long a]
  (inc (inc a)))
(def temp ["test", 2.48])
(map inc2 temp)

Would also fail. Because the type checker would infer that the vector has 
String or Double as type, and inc2 expects none of these.

Or:

(conj ["a", "b"] "c")

would still work.

(conj ^Vec ["a", "b"] 10)

would fail.

Now I don't know, maybe this is too simple, not really useful, or maybe its 
non trivial to implement. But I feel just small type checks like that could 
be useful, and they wouldn't be too burdening.

On Saturday, 15 October 2016 15:14:08 UTC-7, Didier wrote:
>
> I know a lot of people like to say how unhelpful Java like static typing 
> is, and only more powerful type systems of the ML family add value, but 
> I've been wondering recently if for Clojure it wouldn't make more sense to 
> simply extend the type hints to enable an optional Java like static typing 
> schemI the.
>
> It is my understanding that ML style static typing is incredibly difficult 
> to add properly and without compromise to a dynamic language. That doing so 
> limits the scope of type inference, rendering the task of adding type info 
> more tedious then in ML languages themselves.
>
> ML style static typing provide enhanced safety grantees, but seem to add 
> too much complexity to Clojure to be practical. What about a Java like 
> static typing scheme though?
>
> I haven't found in practice that the safety of Clojure was an issue, as 
> the REPL workflow tend to promote quite a lot of testing. So I'm not too 
> worried about needing the state of the art of provable correctness for my 
> programs. What has been a biggest cause of issue to me was refactoring and 
> shared code base across a team. Those last two use cases are actually 
> pretty well handled by Java like static type checking. Is it a powerful 
> type checker, not really, but it enables most trivial type errors to be 
> caught early, and it allows easier integration points for other devs to 
> follow, as well as documentation for functions, better tools support and 
> easier refactoring, while also enabling performance optimizations.
>
> I have limited knowledge in typing systems, and have no idea how easy it 
> is to implement them, but as a user of Clojure, I feel like I would find an 
> optional Java like static typing a great addition, one that I am more 
> willing to use and benefit from then Typed Clojure's more complex ML style 
> type checking.
>
> What do other think?
> Can anyone with better knowledge tell me if this would be feasible or if 
> adding such gradual typing system is effectively as hard as adding ML style 
> type checking?
>

-- 
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: Addressing Matthias Felleisen's concerns?

2016-11-05 Thread Didier
Cool, I'm looking forward to it. Seems like that would greatly enhance 
TypedClojure's usefulness.

On Monday, 9 May 2016 15:44:46 UTC-7, Ambrose Bonnaire-Sergeant wrote:
>
> Josh is correct. I'm currently working on merging this work now that my 
> courses are over.
>
> Thanks,
> Ambrose
>
> On Mon, May 9, 2016 at 6:32 PM, Josh Tilles  > wrote:
>
>> On Monday, May 9, 2016 at 5:36:53 PM UTC-4, Didier wrote:
>>>
>>> At Clojurewest 2016, Matthias Felleisen gave a great keynote about the 
>>> pragmatism of soundness for maintening large code bases. He mentioned that 
>>> adding type gradually was useful, but only when the border between typed 
>>> land and untyped land is guarded. He mentioned how Racket does that. He 
>>> also talked about the cost of doing so, which seem to remain an open 
>>> question.
>>>
>>> I'm wondering if any of this has been taken up by somebody in Clojure to 
>>> try to do the same? My understanding is typed clojure does not protect the 
>>> border between typed and untyped. Therefore, you do not have the guarantee 
>>> that your typed code will be correct for all its usage.
>>>
>> I believe that Ambrose (the core developer/maintainer of Typed Clojure) 
>> has been focusing on that very topic as of late: CTYP-309: “Export typed 
>> vars with contracts to untyped namespaces” 
>> <http://dev.clojure.org/jira/browse/CTYP-309>.
>>
>>> Also, does anyone know exactly what he meant by the cost? Is doing 
>>> gradual typing causing slower runtimes, slower compilation, does it hamper 
>>> the dynamism, etc.
>>>
>>  I expect that dynamically-checked contracts would (at least) cause 
>> slower runtimes in the cases of untyped-calling-typed code or 
>> typed-calling-untyped code; I think typed-calling-typed code would skip the 
>> runtime contract verification.
>>
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to 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: Good way of handling metric gathering?

2016-11-12 Thread Didier
You could use: https://github.com/technomancy/robert-hooke

Its basically an AOP library for Clojure.

You can use "with-hooks-disabled" in your tests to disable the hooks that 
have side effects.

On Friday, 11 November 2016 21:42:59 UTC-8, Shantanu Kumar wrote:
>
> Hi Tianxiang,
>
> In my experience a good way to decouple a non-trivial fn with metrics is 
> to make the fn provide hooks for various events when metrics may be 
> gathered.
>
> (defn nop [& args])
>
> (defn foo->bar [foo {:keys [on-foo on-bar] :or {on-foo nop on-bar nop} :as 
> options}]
>   (on-foo)
>   (let [bar (produce-bar foo)]
> (on-bar)
> bar))
>
> Now, when unit testing for functionality of foo->bar you can pass {} as 
> options, which wouldn't do any metrics collection. In actual usage, or for 
> unit testing metrics collection, you would pass {:on-foo #(counter/inc! 
> foo-counter) :on-bar #(counter/inc! bar-counter)} as options.
>
> This is a small fn, so it may not be apparent how can providing hooks be 
> useful, but for large fns with multiple metrics-collection I've found 
> providing hooks to be working quite well.
>
> HTH
>
> Shantanu
>
> On Saturday, 12 November 2016 08:24:40 UTC+5:30, Tianxiang Xiong wrote:
>>
>> What are some good ways of handling metric gathering (or, more generally, 
>> AOP) in Clojure?
>>
>> Suppose we have an application in which there is a transformation 
>> function, foo->bar. Every time a foo is input to foo->bar, we'd like to 
>> increment the foo-counter. Every time a bar is produced, we'd like to 
>> increment the bar-counter.
>>
>> To keep foo->bar pure, we can wrap foo->bar in another function like:
>>
>> (fn [& args]
>>   (counter/inc! foo-counter)
>>   (let [result (apply f args)]
>> (counter/inc! bar-counter)
>> result))
>>
>> But the side effect of incrementing counters makes it difficult to write 
>> a unit test.
>>
>> I have a vague idea of what I'd *like* to see, which is the function 
>> returning:
>>
>>- The result
>>- Some operation to be carried out, OR some data allowing the 
>>receiver to carry out some operation?
>>
>> I'm sure this is not a new problem for Clojure applications; what are 
>> some strategies for handling 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.


Help me understand what part of this code is slow, and how to make it faster?

2016-11-15 Thread Didier
Hey all,

I came upon a benchmark of F#, Rust and OCaml, where F# performs much 
faster then the other two. I decided for fun to try and port it to Clojure 
to see how Clojure does. Benchmark link: 
https://github.com/c-cube/hashset_benchs

This is my code for it: 
https://gist.github.com/didibus/1fd4c00b69d927745fbce3dcd7ca461a

(ns hash-set-bench
  "A Benchmark I modified to Clojure from:
   https://github.com/c-cube/hashset_benchs";)

(defn iterNeighbors [f [i j]]
  (f [(dec i) j])
  (f [(inc i) j])
  (f [i (dec j)])
  (f [i (inc j)]))

(defn nth* [n p]
  (loop [n n s1 #{p} s2 #{}]
(if (= n 0)
  s1
  (let [s0 (atom #{})]
(letfn [(add [p]
 (when (not (or (contains? s1 p) (contains? s2 p)))
   (reset! s0 (conj @s0 p]
   (doseq [p s1] (iterNeighbors add p))
   (recur (dec n) @s0 s1))

#_(printf "result is %d" (count (time (nth* 2000 [0 0]

And here's the F# code: 
https://github.com/c-cube/hashset_benchs/blob/master/neighbors2.fsx

Currently, this takes about 30s in Clojure, while it only takes around 3s 
for OCaml, Rust and F#.

>From what I see, the differences between my code and theirs are:

   - Lack of a Point struct, I'm just using a vector.
   - They use a mutable set, I don't.
   - They overrode Hashing for their point struct, as well as equality. I 
   rely on Clojure's default hashing, and vector equality.

I'm not sure if any of these things should really impact performance that 
much though. And what I could do in Clojure if I wanted to improve it.


Any Help?


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.


Re: Clojure Repos - Some Dependencies are Not In Clojars

2016-11-15 Thread Didier
I feel like even if Clojars is not firewalled, you should probably get OSS 
approval from your legal team before important Clojars libs. Just a 
suggestion.

On Wednesday, 9 November 2016 05:55:41 UTC-8, Vitaly Peressada wrote:
>
> Hi All,
>
> FWIK the community uses both Maven Central and Clojars. But it appears 
> that Clojars does not have ALL Clojure dependencies. It is an annoying 
> issue in my present BIG company where Maven Central is blocked and it takes 
> 2-3 weeks to approve OSS library and upload it to company internal repo. 
> Luckily Clojars is proxied via Nexus and is available.
>
> Two examples are:
> org.clojure/tools.nrepl 0.2.12
> org.tcrawley:dynapath:jar:0.2.4 (dependency of 
> cider/cider-nrepl/0.15.0-SNAPSHOT)
>
> Don't know what historical context is but it would make sense to have ALL 
> deps in Clojars with some duplication in Maven Central (may be for clojure 
> itself, etc.)
>

-- 
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 me understand what part of this code is slow, and how to make it faster?

2016-11-21 Thread Didier
I experimented with this a lot, and took everyone's advice, and this is the 
fastest I got, even faster then Michael Gardner's answer.

(deftype point5 [^long i ^long j]
  Object
  (equals [this that] (and (= (.i this) (.i ^point5 that))
   (= (.j this) (.j ^point5 that
  (hashCode [this] (+ (.i this) (* 4000 (.j this)

(defn iter-neighbors5 [f ^point5 p]
  (let [i ^long (.i p)
j ^long (.j p)]
(f (->point5 (dec i) j))
(f (->point5 (inc i) j))
(f (->point5 i (dec j)))
(f (->point5 i (inc j)

(defn nth5 [n p]
  (loop [n ^long n
 s1 (HashSet. [p])
 s2 (HashSet.)]
(if (zero? n)
  s1
  (let [s0 (HashSet.)]
(letfn [(add [p]
 (when (not (or (.contains s1 p) (.contains s2 p)))
   (.add s0 p)))]
   (doseq [p s1] (iter-neighbors5 add p))
   (recur (dec n) s0 s1))

This is basically the closest I can get to the F#, Rust and OCaml solution. 
I create a minimal class where I overload equals and hashCode using the 
same logic the F# solution uses. It gives me equal performance to F# on my 
machine: 3s.

Here's the run down from slowest to fastest with a size of 100 using 
criterium. All of them I did my best to avoid reflection and boxed numeric 
and had enabled uncheck math. Granted I did not find that boxing and 
unchecked math really provided a drastic improvement in my case.:

   1. Using a record to hold the point with a java HashSet - 826ms
   2. Using a struct to hold the point with a java HashSet - 246ms
   3. Using a volatile with a Clojure HashSet and vectors for point - 50ms
   4. Using an atom with a Clojure HashSet and vectors for point - 51ms
   5. Using java.awt Point with a java HashSet and add as a closure - 41ms
   6. Using vectors with a java HashSet, but with add done inside doseq, 
   without a closure - 11ms
   7. Using vectors with a java HashSet and add as a closure - 9ms
   8. Using java.awt Point with a java HashSet, but with add done inside 
   doseq, without a closure (Michael Gardner's solution) - 7.5ms
   9. Using deftype with overloaded equals and hashCode as points with a 
   java HashSet, but with add done inside doseq, without a closure - 6ms
   10. Using deftype with overloaded equals and hashCode as points with a 
   java HashSet and add as a closure - 4ms
   
This is what I gathered from my experiments:

   - Using java's mutable HashSet instead of Clojure's persistent hashset 
   gave a significant speed improvement. From 30s to 5s. This was the most 
   significant speed boost.
   - Records are really slow, probably because of the time to instantiate 
   them. So slow, that even though it was using a mutable HashSet, it was 
   still slower then Clojure sets with vectors.
   - Similarly, structs are also pretty slow, which I'd guess is also 
   because of instantiating them. Though they were faster then Records.
   - Volatile did not noticeably improve performance compared to Atom, but 
   I learned about them today, did not know Clojure had that.
   - Unsafe Math and type hinting numeric to get rid of boxing did not 
   noticeably improve performance, but I learned about it today too. Speaking 
   of which, is ^long faster then ^int?
   - Vectors were as fast as java.awt.Point. Though for some reason, 
   putting the java.awt.Point inside a closure slowed the whole thing down 
   quite a bit. Where as without it, using a closure actually performed 
   faster. Maybe I did something wrong here, since I find that a little 
   surprising and confusing.
   - Defining my own type optimized for my specific use-case was the 
   fastest. deftypes are lightweight, and instantiate quickly, and with the 
   custom equals and hashCode tailored to the problem, they performed best, 
   matching F# and beating out OCaml and Rust.
   

On Tuesday, 15 November 2016 19:39:43 UTC-8, Didier wrote:
>
> Hey all,
>
> I came upon a benchmark of F#, Rust and OCaml, where F# performs much 
> faster then the other two. I decided for fun to try and port it to Clojure 
> to see how Clojure does. Benchmark link: 
> https://github.com/c-cube/hashset_benchs
>
> This is my code for it: 
> https://gist.github.com/didibus/1fd4c00b69d927745fbce3dcd7ca461a
>
> (ns hash-set-bench
>   "A Benchmark I modified to Clojure from:
>https://github.com/c-cube/hashset_benchs";)
>
> (defn iterNeighbors [f [i j]]
>   (f [(dec i) j])
>   (f [(inc i) j])
>   (f [i (dec j)])
>   (f [i (inc j)]))
>
> (defn nth* [n p]
>   (loop [n n s1 #{p} s2 #{}]
> (if (= n 0)
>   s1
>   (let [s0 (atom #{})]
> (letfn [(add [p]
>  (when (not (or (contains? s1 p) (contains? s2 p)))
>(reset! s0 (conj @s0 p]
>(doseq [p s1] (iterNeighbors add p))
>

Re: Help me understand what part of this code is slow, and how to make it faster?

2016-11-21 Thread Didier
I tried it with the safe equals, and it is slightly slower, but still 
faster then all others at 4.5ms. The non safe equals gives me 4s. Though 
this is now within my error margin. If ire-run quick-bench, I sometime get 
a mean equal for each, so I don't think the instance check adds that much 
overhead if any at all.

@miner: Doesn't using the flag (set! *unchecked-math* :warn-on-boxed) gives 
me unchecked math automatically? I was under the impression that +, -, /, * 
etc. would all now perform in an equal way to unchecked-add, etc. If not, 
what is the difference?

@Andy: I tried with the "1.9.0-alpha14" version, and Records were still 
just as slow as with "1.8.0". Maybe I'm using them wrong.

On Tuesday, 15 November 2016 19:39:43 UTC-8, Didier wrote:
>
> Hey all,
>
> I came upon a benchmark of F#, Rust and OCaml, where F# performs much 
> faster then the other two. I decided for fun to try and port it to Clojure 
> to see how Clojure does. Benchmark link: 
> https://github.com/c-cube/hashset_benchs
>
> This is my code for it: 
> https://gist.github.com/didibus/1fd4c00b69d927745fbce3dcd7ca461a
>
> (ns hash-set-bench
>   "A Benchmark I modified to Clojure from:
>https://github.com/c-cube/hashset_benchs";)
>
> (defn iterNeighbors [f [i j]]
>   (f [(dec i) j])
>   (f [(inc i) j])
>   (f [i (dec j)])
>   (f [i (inc j)]))
>
> (defn nth* [n p]
>   (loop [n n s1 #{p} s2 #{}]
> (if (= n 0)
>   s1
>   (let [s0 (atom #{})]
> (letfn [(add [p]
>  (when (not (or (contains? s1 p) (contains? s2 p)))
>(reset! s0 (conj @s0 p]
>(doseq [p s1] (iterNeighbors add p))
>(recur (dec n) @s0 s1))
>
> #_(printf "result is %d" (count (time (nth* 2000 [0 0]
>
> And here's the F# code: 
> https://github.com/c-cube/hashset_benchs/blob/master/neighbors2.fsx
>
> Currently, this takes about 30s in Clojure, while it only takes around 3s 
> for OCaml, Rust and F#.
>
> From what I see, the differences between my code and theirs are:
>
>- Lack of a Point struct, I'm just using a vector.
>- They use a mutable set, I don't.
>- They overrode Hashing for their point struct, as well as equality. I 
>rely on Clojure's default hashing, and vector equality.
>
> I'm not sure if any of these things should really impact performance that 
> much though. And what I could do in Clojure if I wanted to improve it.
>
>
> Any Help?
>
>
> 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.


Re: [ANN] psq.clj 0.0.2 – Persistent Priority Search Queues

2016-11-22 Thread Didier
Great work. I love the Clojure state for data-structures. People often 
underestimate how much access to quality data-structures is important for a 
language. By the way, www.data.avl is not a valid link.

On Sunday, 20 November 2016 12:32:31 UTC-8, Michał Marczyk wrote:
>
> Hi,
>
> I am pleased to announce the 0.0.2 release of psq.clj, a Clojure
> priority search queue library based on Ralf Hinze's priority search
> pennants (see Ralf Hinze, "A Simple Implementation Technique for
> Priority Search Queues"):
>
>   https://github.com/michalmarczyk/psq.clj
>
>   https://clojars.org/psq.clj
>
> Priority search queues simultaneously behave like sorted maps with
> respect to their keys and like priority queues with respect to their
> entries, with the priority queue ordering based on the values, or
> priorities, attached to the keys. Additionally they support several
> operations that blend the sorted map and priority queue aspects
> together, such as "peek in key range" (retrieve a minimum-priority
> entry – NB. ties on priorities are supported – within the given key
> range) and optimized subseq-like traversals of key ranges that only
> return those entries whose priorities fall below a certain threshold
> (this is much more efficient than subseq + filter on a regular sorted
> map).
>
> psq.clj priority search queues support the full data.avl abstract data
> type (with the exception of the transient API which I am not sure
> would bring a significant return on the additional memory cost in this
> context). The full public API is as follows:
>
>   ;;; there is a single public namespace:
>   (require '[psq.clj :as psq])
>
>
>   ;;; 1. factory functions
>
>   ;; the psq.clj counterpart to clojure.core/sorted-map:
>   (psq/psqueue key priority …)
>   ;= {key priority …}
>
>   ;; a version of the above that takes keys+priorities in a seqable:
>   (psq/psqueue* [key priority …])
>
>   ;; a factory that accepts a map or seqable of map entries:
>   (psq/psq {key priority …})
>   (psq/psq [[key priority] …])
>
>   ;; versions of the above that take *two* custom comparators: the
>   ;; first one determines the PSQ's key order, the second one is used
>   ;; for priorities:
>   (psq/psqueue-by > > key priority …) ; reverse numeric order on keys
>   ; and priorities
>
>   psq/psqueue-by*, psq/psq-by ; like psq/psqueue*, psq/psq, but with
>   ; custom comparators
>
>
>   ;;; 2. regular sorted map API; NB. (r)(sub)seq use key order
>
>   (seq (psq/psqueue 0 10 1 9))
>   ;= ([0 10] [1 9])
>   
>   ;; also supported: assoc, dissoc, conj, rseq, subseq, rsubseq
>
>
>   ;;; 3. nearest neighbour lookups
>   (psq/nearest (psq/psq {0 1 4 5 9 10}) > 3)
>   ;= [4 5]
>
>
>   ;;; 4. nth, rank in key order
>
>   (nth (psq/psqueue 0 3 6 -3) 0)
>   ;= [0 3]
>
>   (psq/rank (psq/psqueue 0 3 6 -3) 6) ; returns long, -1 for not found
>   ;= 1
>
>
>   ;;; 5. priority queue API based on values/priorities
>
>   (peek (psq/psqueue 0 3 1 -3))
>   ;= [1 -3]
>
>   (pop (psq/psqueue 0 3 1 -3))
>   ;= {0 3}
>
>   ;; seq over the PSQ in order of non-decreasing priorities
>   (psq/priority-seq (psq/psqueue 0 3 1 -3))
>   ;= ([1 -3] [0 3])
>
>
>   ;;; 6. splits, subranges – with structural sharing in the common
>   ;;;parts, but no holding on to keys outside the stated range for
>   ;;;GC purposes
>
>   ;; return a vector of
>   ;;
>   ;;   1. a fully independent PSQ comprising the entries of the
>   ;;  input PSQ to the left of the given key,
>   ;;
>   ;;   2. the entry at the given key, or nil if not present,
>   ;;
>   ;;   3. a fully independent PSQ comprising the entries of the
>   ;;  input PSQ to the right of the given key:
>   (psq/split (psq/psqueue* (range 10)) 4)
>   ;= [{0 1 2 3} [4 5] {6 7 8 9}]
>
>   ;; like subseq, but returns an independent PSQ
>   (psq/subrange (psq/psqueue* (range 10)) >= 4 < 8)
>   ;= {4 5 6 7}
>
>
>   ;;; 7. priority-bounded traversals:
>   (psq/seq<= a-psq priority-upper-bound)
>
>   ;; also supported: rseq<=, subseq<=, rsubseq<= (the latter two
>   ;; with subseq/rsubseq-like arguments to specify key bounds) and
>   ;; < variants of all of the above (seq< etc.)
>
> All of the above operations can be performed in O(log n) time, with
> the exception of peek, which takes constant time, and seq-like
> operations, which are sensitive to the number of entries actually
> produced. Priority-bounded traversals take O(r(log n - log r) + r)
> time, where r is the number of entries actually returned.
>
> In practice, psq.clj priority search queues are slower than Clojure's
> built-in sorted maps for pure sorted-map operations, typically by a
> factor of 2 to 4. In return, the PSQ operations are very performant;
> subseq<= can be over three orders of magnitude faster than the
> equivalent combination of subseq and filter applied to a regular
> sorted map, subrange takes tens of microseconds when the size of the
> input is on the order of hundreds o

Re: Help me understand what part of this code is slow, and how to make it faster?

2016-11-22 Thread Didier
@Marczyk, I did try your improvements, and it shaved off 2 seconds, from 4s 
for the nth5 to 2s for your implementation.

I'm curious to try it one change at a time to see if any one of the changes 
was responsible for a bigger part, or if its an its of equal improvements 
that total up to a big speed boost.

On Tuesday, 15 November 2016 19:39:43 UTC-8, Didier wrote:
>
> Hey all,
>
> I came upon a benchmark of F#, Rust and OCaml, where F# performs much 
> faster then the other two. I decided for fun to try and port it to Clojure 
> to see how Clojure does. Benchmark link: 
> https://github.com/c-cube/hashset_benchs
>
> This is my code for it: 
> https://gist.github.com/didibus/1fd4c00b69d927745fbce3dcd7ca461a
>
> (ns hash-set-bench
>   "A Benchmark I modified to Clojure from:
>https://github.com/c-cube/hashset_benchs";)
>
> (defn iterNeighbors [f [i j]]
>   (f [(dec i) j])
>   (f [(inc i) j])
>   (f [i (dec j)])
>   (f [i (inc j)]))
>
> (defn nth* [n p]
>   (loop [n n s1 #{p} s2 #{}]
> (if (= n 0)
>   s1
>   (let [s0 (atom #{})]
> (letfn [(add [p]
>  (when (not (or (contains? s1 p) (contains? s2 p)))
>(reset! s0 (conj @s0 p]
>(doseq [p s1] (iterNeighbors add p))
>(recur (dec n) @s0 s1))
>
> #_(printf "result is %d" (count (time (nth* 2000 [0 0]
>
> And here's the F# code: 
> https://github.com/c-cube/hashset_benchs/blob/master/neighbors2.fsx
>
> Currently, this takes about 30s in Clojure, while it only takes around 3s 
> for OCaml, Rust and F#.
>
> From what I see, the differences between my code and theirs are:
>
>- Lack of a Point struct, I'm just using a vector.
>- They use a mutable set, I don't.
>- They overrode Hashing for their point struct, as well as equality. I 
>rely on Clojure's default hashing, and vector equality.
>
> I'm not sure if any of these things should really impact performance that 
> much though. And what I could do in Clojure if I wanted to improve it.
>
>
> Any Help?
>
>
> 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.


Re: Help me understand what part of this code is slow, and how to make it faster?

2016-11-24 Thread Didier
Here's my findings:

Speed increase from most increase to least:
* Pre-sizing the HashSet - from 4.7ms to 3.7ms
* Inlining - from 4.7ms to 3.9ms
* Using point. constructor instead of ->point - from 2.4ms to 2ms
* Using non relfective HashSet init - from 2.36ms to 2.17ms
* Using iterator instead of doseq - from 2.17ms to 2.07ms

All in all, after this whole experiment, those would be my go to 
recommendations if wanting to optimize something in Clojure:

- If you are creating a lot of temporary structures use deftype for optimum 
performance, avoid records, and go for vectors and maps as a good middle 
ground.
- If you are adding a lot to a data-structure, resort to a mutable version 
for best performance.
- If using a mutable data-structure, try to pre-size them, if you plan on 
them growing a lot.
- If performance is critical, try inlining the functions you call most, 
things called from a loop are great candidates.
- Avoid using ->wtv style constructors, prefer wtv. instead for best 
performance.
- Avoid reflection and checked boxed math, especially if inside a loop.
- Try an iterator as the fastest way to iterate over a structure, though at 
this point, you're probably spending too much time optimizing.

On Tuesday, 15 November 2016 19:39:43 UTC-8, Didier wrote:
>
> Hey all,
>
> I came upon a benchmark of F#, Rust and OCaml, where F# performs much 
> faster then the other two. I decided for fun to try and port it to Clojure 
> to see how Clojure does. Benchmark link: 
> https://github.com/c-cube/hashset_benchs
>
> This is my code for it: 
> https://gist.github.com/didibus/1fd4c00b69d927745fbce3dcd7ca461a
>
> (ns hash-set-bench
>   "A Benchmark I modified to Clojure from:
>https://github.com/c-cube/hashset_benchs";)
>
> (defn iterNeighbors [f [i j]]
>   (f [(dec i) j])
>   (f [(inc i) j])
>   (f [i (dec j)])
>   (f [i (inc j)]))
>
> (defn nth* [n p]
>   (loop [n n s1 #{p} s2 #{}]
> (if (= n 0)
>   s1
>   (let [s0 (atom #{})]
> (letfn [(add [p]
>  (when (not (or (contains? s1 p) (contains? s2 p)))
>(reset! s0 (conj @s0 p]
>(doseq [p s1] (iterNeighbors add p))
>(recur (dec n) @s0 s1))
>
> #_(printf "result is %d" (count (time (nth* 2000 [0 0]
>
> And here's the F# code: 
> https://github.com/c-cube/hashset_benchs/blob/master/neighbors2.fsx
>
> Currently, this takes about 30s in Clojure, while it only takes around 3s 
> for OCaml, Rust and F#.
>
> From what I see, the differences between my code and theirs are:
>
>- Lack of a Point struct, I'm just using a vector.
>- They use a mutable set, I don't.
>- They overrode Hashing for their point struct, as well as equality. I 
>rely on Clojure's default hashing, and vector equality.
>
> I'm not sure if any of these things should really impact performance that 
> much though. And what I could do in Clojure if I wanted to improve it.
>
>
> Any Help?
>
>
> 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.


Closure for object pattern? A good idea?

2016-12-09 Thread Didier
I'm wondering what everyone thinks of using closures to mimic a simplistic 
object system in Clojure? I'm not sure what to think of it yet, but the 
idea is that you wrap object fields inside a closed function, and it 
returns a map of methods that operates over those fields.

Here's an example of using this pattern to implement a StopWatch:

(import [java.lang System])
(defn new-stopwatch []
  (let [start-time (atom nil)
elapsed (atom 0)]
{:start (fn []
  (when (nil? @start-time)
(reset! start-time (System/currentTimeMillis
 :stop (fn []
 (when-not (nil? @start-time)
   (reset! elapsed
   (+ @elapsed
  (- (System/currentTimeMillis) @start-time)))
   (reset! start-time nil))
 @elapsed)
 :reset (fn []
  (reset! start-time nil)
  (reset! elapsed 0)
  @elapsed)
 :elapsed (fn []
(if-not (nil? @start-time)
(- (System/currentTimeMillis) @start-time)
@elapsed))}))

(let [sw1 (new-stopwatch)
  sw2 (new-stopwatch)]
  ((:start sw1))
  ((:start sw2))
  (Thread/sleep 100)
  ((:reset sw1))
  ((:start sw1))
  (println (str "Elapsed for SW1: " ((:elapsed sw1
  (println (str "Elapsed for SW2: " ((:elapsed sw2
  (Thread/sleep 100)
  (println (str "SW1: " ((:stop sw1
  (println (str "SW2: " ((:stop sw2)

I find for certain things, like a stopwatch, this pattern is actually 
pretty nice. I can't think of any alternative way to do this in Clojure 
that I'd like better actually.

What are your thoughts?

-- 
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: Closure for object pattern? A good idea?

2016-12-10 Thread Didier
Logan's point about being able to add new functions on a stopwatch is 
valid. That's often the argument to why protocols are better then classic 
OO. Though I still feel like in some scenarios, I think this is a good 
pattern, and can serve us better, the stopwatch being one good example.

Nothing in the pattern necessitate this to be mutable either, though I 
guess this pattern does seem to have some of its advantages from when you 
need mutability for some reason. Then I like how it isolates the mutable 
data behind the functionality.

It feels like a lighter weight version of both OO and protocols/records. 
I'm curious to benchmark it against records, which is what I would have 
used before for something like a stopwatch.

I think this could come in handy when doing libraries with options. My 
current pattern was to have a function create an options, and then the user 
would need to manage the options map, and pass it to all my library 
functions. Or I would use a var instead the library to store the options 
map, and offer it as a binding so users could rebind their own options. The 
problem with the latter is that you can't run the library with two 
different option set at the same time, while the former forces you to have 
to manage an options map and pass it around everywhere. So I feel there's 
something I could do here, with wrapping everything in this pattern, and 
having the options be captured in the closure.

On Friday, 9 December 2016 23:47:34 UTC-8, Didier wrote:
>
> I'm wondering what everyone thinks of using closures to mimic a simplistic 
> object system in Clojure? I'm not sure what to think of it yet, but the 
> idea is that you wrap object fields inside a closed function, and it 
> returns a map of methods that operates over those fields.
>
> Here's an example of using this pattern to implement a StopWatch:
>
> (import [java.lang System])
> (defn new-stopwatch []
>   (let [start-time (atom nil)
> elapsed (atom 0)]
> {:start (fn []
>   (when (nil? @start-time)
> (reset! start-time (System/currentTimeMillis
>  :stop (fn []
>  (when-not (nil? @start-time)
>(reset! elapsed
>(+ @elapsed
>   (- (System/currentTimeMillis) @start-time)))
>(reset! start-time nil))
>  @elapsed)
>  :reset (fn []
>   (reset! start-time nil)
>   (reset! elapsed 0)
>   @elapsed)
>  :elapsed (fn []
> (if-not (nil? @start-time)
> (- (System/currentTimeMillis) @start-time)
> @elapsed))}))
>
> (let [sw1 (new-stopwatch)
>   sw2 (new-stopwatch)]
>   ((:start sw1))
>   ((:start sw2))
>   (Thread/sleep 100)
>   ((:reset sw1))
>   ((:start sw1))
>   (println (str "Elapsed for SW1: " ((:elapsed sw1
>   (println (str "Elapsed for SW2: " ((:elapsed sw2
>   (Thread/sleep 100)
>   (println (str "SW1: " ((:stop sw1
>   (println (str "SW2: " ((:stop sw2)
>
> I find for certain things, like a stopwatch, this pattern is actually 
> pretty nice. I can't think of any alternative way to do this in Clojure 
> that I'd like better actually.
>
> What are your thoughts?
>

-- 
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: Private multimethods possible?

2017-01-09 Thread Didier
How would you declare a namespace within a namespace? Or two namespaces in 
the same file?

On Friday, 23 October 2009 04:41:13 UTC-7, Meikel Brandmeyer wrote:
>
> Hi, 
>
> On Oct 23, 8:45 am, Christophe Grand  wrote: 
>
> > Other solutions are to use @#'ns/private-var to access private vars from 
> the 
> > macro or to make the macro shallow using a public (usually higher-order) 
> > helper function (is this possible in the general case?). 
>
> It is not 100% possible in the general case but it the vast majority 
> of the cases, I'd say. 
>
> Concerning the private Vars: I'd actually suggest to dispose them 
> entirely. Namespaces can be split into an interface space contain the 
> public interface. It can 'use' a special internal namespace, which 
> does not belong to the public API of the library. All defs are normal, 
> public defs. 
>
> This approach solves all problems: 
> - The user knows, what the public API is. 
> - The macros can access everything they need. 
> - Code completion only finds the public stuff. 
> - It doesn't need modifications like a 'semi-private' or 'protected' 
> flag. 
>
> I think, Stephen exercised this approach in c.c.sql. 
>
> Sincerely 
> Meikel 
>
> PS: My opinion: design your library to be used with require and :as 
> instead of use. Document the public API. That is the contract. The 
> contract stays valid whether the system enforces it or 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.


Re: Private multimethods possible?

2017-01-11 Thread Didier
Maybe you're right in not recommending this, but I find it at first glance to 
be quite nice. Now, I wouldn't keep switching namespace back and forth, but 
having two sections in the file, one the public API at the top, and everything 
else at the bottom in a private namespace, that's quite nice I'd say. 

I hate juggling through files, like C++ header and body files annoy me a lot.

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


Pattern matching Vs destructuring?

2017-01-26 Thread Didier
Some languages have pattern matching, and Clojure is said to not have it 
(without a library), but it does have destructuring.

It seems to me that destructuring is the same as pattern matching, except that 
it can only be used inside function arguments, where as pattern matching can 
also be used when assigning a value or inside case switch statements.

Is that truly the only difference? And if so, why the different terminology?

-- 
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] Odin 0.2.0 - Query DSL for Clojure

2017-02-24 Thread Didier
How does this compare to Specter?

On Thursday, 23 February 2017 13:34:16 UTC-8, Alan Thompson wrote:
>
> Just came across this - it looks very cool!
> Alan
>
> On Sat, Dec 10, 2016 at 7:14 AM, Timothy Baldridge  > wrote:
>
>> I just released the first official version of Odin (
>> https://github.com/halgari/odin). Odin is a declarative, extensible 
>> query DSL for Clojure that leverages transducers to provide a high amount 
>> of generality while still maintaining acceptable performance. 
>>
>> One of the biggest features of Odin is its ability to rapidly index and 
>> query "normal" Clojure data structures. Here is a quick example of this 
>> feature in practice: 
>>
>> (let [orders [{:customer/name "Sam"
>>:customer/id   3411}
>>   {:customer/id 3411
>>:order/items {1212 3}}
>>   {:customer/id 3411
>>:order/items {2232 2 4242 3}}
>>   {:item/id1212
>>:item/price 40.0}
>>   {:item/id2232
>>:item/price 100}
>>   {:item/id4242
>>:item/price 1.99}]]
>>   (->> (o/for-query
>>  (o/and
>>(d/query orders ?customer :customer/name "Sam")
>>(d/query orders ?customer :customer/id ?id)
>>(d/query orders ?order :customer/id ?id)
>>(d/query-in orders ?order [:order/items ?item-id] ?qty)
>>(d/query orders ?item :item/id ?item-id)
>>(d/query orders ?item :item/price ?price))
>>  (* ?qty ?price))
>>(reduce + 0)))
>>
>> ;; => 325.97
>>
>>
>> In this example we are given a vector of maps, we are then finding a 
>> customer by name,
>>
>> then walking a path through the data to find all the items that customer 
>> ordered, the
>>
>> total price is then calculated via the normal multiply and sum. 
>>
>>
>> There are several other features supported by Odin, including transformation 
>> of data
>>
>> (based on a query), tabling, Datomic support, and much more. 
>>
>>
>> I also did a video series on the development process of Odin if anyone is 
>> interested: 
>> (https://www.youtube.com/watch?v=JyKySmcTR4g)
>>
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to 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] Odin 0.2.0 - Query DSL for Clojure

2017-02-25 Thread Didier
Interesting, thanks.

FYI: I do not see that question in the QA of the readme. I see Datalog and 
core.logic comparison, but not specter.

On Friday, 24 February 2017 17:11:16 UTC-8, tbc++ wrote:
>
> It's in the QA in the readme, but specter only queries a single path 
> through the data. Odin supports relations, joins, recursive rules, tabling, 
> etc. 
>
> Currently Specter will probably perform a bit better, but I hope to close 
> that gap in the future.
>
>
> Timothy
>
> On Fri, Feb 24, 2017 at 5:10 PM Didier > 
> wrote:
>
>> How does this compare to Specter?
>>
>>
>> On Thursday, 23 February 2017 13:34:16 UTC-8, Alan Thompson wrote:
>>
>>> Just came across this - it looks very cool!
>>> Alan
>>>
>> On Sat, Dec 10, 2016 at 7:14 AM, Timothy Baldridge  
>>> wrote:
>>>
>> I just released the first official version of Odin (
>>>> https://github.com/halgari/odin). Odin is a declarative, extensible 
>>>> query DSL for Clojure that leverages transducers to provide a high amount 
>>>> of generality while still maintaining acceptable performance. 
>>>>
>>>> One of the biggest features of Odin is its ability to rapidly index and 
>>>> query "normal" Clojure data structures. Here is a quick example of this 
>>>> feature in practice: 
>>>>
>>>> (let [orders [{:customer/name "Sam"
>>>>:customer/id   3411}
>>>>   {:customer/id 3411
>>>>:order/items {1212 3}}
>>>>   {:customer/id 3411
>>>>:order/items {2232 2 4242 3}}
>>>>   {:item/id1212
>>>>:item/price 40.0}
>>>>   {:item/id2232
>>>>:item/price 100}
>>>>   {:item/id4242
>>>>:item/price 1.99}]]
>>>>   (->> (o/for-query
>>>>  (o/and
>>>>(d/query orders ?customer :customer/name "Sam")
>>>>(d/query orders ?customer :customer/id ?id)
>>>>(d/query orders ?order :customer/id ?id)
>>>>(d/query-in orders ?order [:order/items ?item-id] ?qty)
>>>>(d/query orders ?item :item/id ?item-id)
>>>>(d/query orders ?item :item/price ?price))
>>>>  (* ?qty ?price))
>>>>(reduce + 0)))
>>>>
>>>> ;; => 325.97
>>>>
>>>>
>>>> In this example we are given a vector of maps, we are then finding a 
>>>> customer by name,
>>>>
>>>> then walking a path through the data to find all the items that customer 
>>>> ordered, the
>>>>
>>>> total price is then calculated via the normal multiply and sum. 
>>>>
>>>>
>>>> There are several other features supported by Odin, including 
>>>> transformation of data
>>>>
>>>> (based on a query), tabling, Datomic support, and much more. 
>>>>
>>>>
>>>> I also did a video series on the development process of Odin if anyone is 
>>>> interested: 
>>>> (https://www.youtube.com/watch?v=JyKySmcTR4g)
>>>>
>>>> -- 
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Clojure" group.
>>>>
>>> To post to this group, send email to clo...@googlegroups.com
>>>
>>>
>>>> Note that posts from new members are moderated - please be patient with 
>>>> your first post.
>>>> To unsubscribe from this group, send email to
>>>>
>>> clojure+u...@googlegroups.com
>>>
>>>
>>>> For more options, visit this group at
>>>> http://groups.google.com/group/clojure?hl=en
>>>> --- 
>>>> You received this message because you are subscribed to the Google 
>>>> Groups "Clojure" group.
>>>>
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to clojure+u...@googlegroups.com.
>>>
>>>
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>>

Re: Vars as global thread-locals?

2017-02-25 Thread Didier
"If one needs thread-local storage, you use a Java ThreadLocal directly."

No, you just use a dynamic Var for that or with-local-vars.

Normally, in Clojure, values are bound to symbols. This means that a symbol 
is mapped to a value. In general, you can not change this mapping once it 
is set. This is true in local contexts, such as when using (let) or with 
function arguments.

In cases where you need to change the mapping, you'll need to have an extra 
layer of indirection, since you can not actually change it. To do this, 
Clojure gives you a few constructs such as Vars, Refs, Agents and Atoms.

A Var is a mapping from thread to value, with support for an optional root 
value (like a default value if no value for the current thread exists on 
the Var). So instead of doing Symbol -> Value, you will do Symbol -> 
Var(CurrentThread) -> Value.

By default, Vars just have a root, and you can not dynamically add new 
thread to value mappings to them unless they are declared dynamic.

Now, when you do "def" or what is called "intern", you are creating a new 
mapping from Symbol to Var on the current Namespace. This can be thought of 
as the global context. When you use a symbol, Clojure will first look for 
it inside local contexts, and if it does not find it there, it will look 
for it in the current namespace. If it is a fully qualified symbol, it'll 
go looking for it directly inside the namespace you qualified. What this 
means is that, on a Namespace, you can not map Symbols to Values, you can 
only map Symbols to Vars. In local contexts, you can map symbols to 
whatever you want, but not in the global context.

The reason Clojure always forces you to map symbols to vars at the 
namespace level are unknown to me, but that's what it does.

All that to say, if you want a per-thread value, go ahead and use a dynamic 
Var. You can choose to make it global, by using def, or to make it local, 
by creating a local Var using (with-local-vars). No need to use Java's 
ThreadLocals directly.

Keep in mind that if you have sub-threads, they won't always inherit their 
parent's bindings. They only do inside (future) and if using (bound-fn).

On Wednesday, 8 February 2017 14:39:59 UTC-8, Ernesto Garcia wrote:
>
> Hi Alex, thanks for your thorough response.
>
> It seems to me that Clojure vars are just not intended to be used as 
> thread-locals in general. They happen to use thread-local storage in order 
> to implement dynamic scoping, which is the original intent.
>
> That is why vars are either global (interned in a namespace), or confined 
> to a dynamic scope (via with-local-vars).
>
> If one needs thread-local storage, you use a Java ThreadLocal directly.
>

-- 
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: Vars as global thread-locals?

2017-02-25 Thread Didier
Re-reading your reply, sounds like I might have explained what you already 
know. So to better answer your question:

Dynamic scoping and Java ThreadLocals gives you equal functionality, so I'd 
use them equally. This is because Clojure supports thread bound dynamic 
scope.

On Wednesday, 8 February 2017 14:39:59 UTC-8, Ernesto Garcia wrote:
>
> Hi Alex, thanks for your thorough response.
>
> It seems to me that Clojure vars are just not intended to be used as 
> thread-locals in general. They happen to use thread-local storage in order 
> to implement dynamic scoping, which is the original intent.
>
> That is why vars are either global (interned in a namespace), or confined 
> to a dynamic scope (via with-local-vars).
>
> If one needs thread-local storage, you use a Java ThreadLocal directly.
>

-- 
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: Vars as global thread-locals?

2017-03-04 Thread Didier
Hum, you're having me question myself.

See, I don't think dynamically scoped Vars are intended for anything in 
particular, they are what they are. Yes, they are useful when you need to 
pass configuration down a call stack, as long as you make sure you handle 
the thread-boundaries along the way. They can also be used to share per 
thread data throughout a thread's execution, which is what ThreadLocal in 
java does. So basically, I see two use cases. One, you want shared read 
only data accessible throughout a call stack (for that, they aren't as good 
as true dynamics, because you'll need to manually handle the thread 
boundaries). Or you want shared writable state per-thread, making this not 
per-thread would be dangerous, and can be done if you re-bind it manually 
across threads or when using constructs that does so like future.

The reason they are made per-thread, and not truly dynamic, as in, taking 
on the value down the stack no matter what, is because threads could 
content on it, and it could cause bugs, so its made per-thread for safety. 
Here's an example of such caveat:

(def ^:dynamic *dd*)

(binding [*dd* (atom "John")]
  (let [a (future (reset! *dd* "Bob"))
b (future (reset! *dd* "Mike"))]
@*dd*))

Run this many times, and *dd*'s value could be either Mike or Bob based on 
which threads wins the race.

So the limitation of dynamic scope are inherent to dynamic scoping where 
you have threads. Clojure's attempt at solving this limitation is to make 
them per-thread, with explicit cross thread management through (bound-fn). 
After a few releases, Clojure decided to make future and a few other 
constructs implicitly propagate the dynamic var across threads as that was 
often what people were expecting. All to say, when using dynamic Vars in 
Clojure, you must be thread aware and understand the caveats. There is no 
better way that I'm aware of to handle dynamic scope in a multi-threaded 
environment.

Clojure has root bindings, which Java ThreadLocals does not have. Clojure 
lets you say, if this thread does not have a value for the dynamic Var, 
fetch the root value instead. This is really useful in the use case of read 
only data, like configuration, because you can set a default config. You 
can simulate this in Java with initialValue.

Now, the initialValue lets you do one more thing, it can let you generate 
per-thread values on get, without needing to set it. Such as setting a 
random int on the first get, and subsequent get from that thread will from 
then on return that same generated random int. In Clojure, this is what 
I've seen for such use case:

(def ^:dynamic *id*)

(defmacro with-id [& body]
  `(binding [*id* (rand-int 1)]
~@body))

@(future (with-id (println (str "My request id is: " *id*))
   "Success"))

It's not as convenient per-say, since you have to be explicit and call the 
macro from each Thread before getting the value, but it solves the use case.

Remember that ThreadLocals are more inconvenient to get though, since you 
need to get the ThreadLocal and then get the value out of it. So in some 
ways, Clojure dynamics can also be seen as more convenient.

Up to now, I feel like there is nothing I can not do with a Clojure Dynamic 
Var that I could with a ThreadLocal. They're not identical, but to me, the 
two fulfills equal use cases. And since under the hood, Clojure dynamic 
Vars are implemented with ThreadLocal, they should perform similarly too.

You say you can pass around references of ThreadLocals, but I'm not sure 
what the point of that would be, like what use case would it allow? In 
general, and even the Java doc page says so, you'll put the ThreadLocal in 
a static variable, i.e., private static final ThreadLocal 
threadId. At that point, it's equal to (def ^:dynamic threadId).

Anyways, you can also do that in Clojure, you can pass around the Var such 
as:

(defn printVar [v]
  (println @v))

(with-local-vars [*threadId* 0]
  (.start (Thread. (bound-fn [] (var-set *threadId* 1) (printVar 
*threadId*
  (.start (Thread. (bound-fn [] (var-set *threadId* 2) (printVar 
*threadId*)

I have a function printVar that takes a Var and prints it. Then I create a 
new Var called *threadId* and I set it to two different values, one for 
each Thread. I pass the Var to my Var printing function, and as you can see 
if you run this, it works like it would in Java if you did the same with 
ThreadLocal, printing different values based on the thread.

I hope this helps.


On Friday, 3 March 2017 07:02:21 UTC-8, Ernesto Garcia wrote:
>
> On Sunday, February 26, 2017 at 6:23:28 AM UTC+1, Didier wrote:
>>
>> Dynamic scoping and Java ThreadLocals gives you equal functionality, so 
>> I'd use them equally. This is because Clojure supports thread bound dynamic 
>

Re: Contribute Specter to Clojure core?

2017-03-04 Thread Didier
This got me thinking, what is Clojure?

As I see it, Clojure is a combination of syntax and semantics combined with 
a standard library of functions and macros. Given the Clojure syntax, and 
the Clojure special forms, and Clojure core, I have myself Clojure.

Given that, we should be careful when adding things into core, since that 
makes the burden of writing a Clojure compiler heavier, as anyone who would 
like to port Clojure to another platform would need to re-implement the 
full standard library.

With this in mind, I don't think Specter is essential. In fact, I think the 
things we'd want into Core are everything that handles IO, and the basic 
operations that allows the Clojure language features and semantics.

If we add Specter to core, we make it a first class semantic. Its DSL 
becomes part of the syntax of Clojure.

Now, adding it to contribs could be fine, but I'm not too sure what the 
contribs are. Are they simply packages maintained by the Clojure team 
itself, or are they actually part of the standard library?

Either way, the beauty of Clojure is that libraries are unconstrained, so 
Specter would gain nothing from being added to core or part of contrib 
except for better publicity. So I'd vote for no.

On Saturday, 4 March 2017 15:13:41 UTC-8, Gregg Reynolds wrote:
>
>
>
> On Mar 4, 2017 5:08 PM, "John Newman" > 
> wrote:
>
> Gregg, agreed. But as an aside, as an external library, like core.async, 
> Specter is a shining example of why Clojure (and lisp) is such an awesome 
> platform. 
>
>
> +1001.  to be clear, i am _not_ saying specter is anthing less than 
> awesome. just talking ui.
>
> The fact that Nathan was able to even implement this functionality, in 
> some places even more performant than core idioms, imho proves that Clojure 
> has power well beyond what the core team can or will provide to users. 
> That's a good sell for both Clojure as a platform and for Specter as a 
> library.
>
>
> yepper.
>
> -g
>

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


What makes Clojure Clojure?

2017-03-04 Thread Didier
The Specter post about if it should be made into core or not got me 
wondering what makes Clojure Clojure.

I'm trying to wrap my head around what is the most minimal set of things 
that uniquely make up Clojure.

Right now, in that set I've got:

   - The Clojure syntax and its semantics
   - The Clojure special forms and their semantics
   - The Clojure core libraries and their semantics

So if I implemented a compiler that worked with the above set, it would be 
a valid Clojure compiler.

Now, ClojureScript appears to me like it is not Clojure, but a dialect of 
it. I say that because it breaks some of the syntax semantics of Clojure, 
like not allowing macros in the same namespace as functions. It also breaks 
some of the core semantics, like def creating standard JS vars and not 
Clojure Vars. In this respect, a language like hy-lang is also a Clojure 
dialect, granted it shares even less of the Clojure set.

Is ClojureCLR a dialect of Clojure, or is it a true Clojure implementation?

One last thing that is interesting about Clojure versus other languages is 
that it does not provide standard IO. These two things make it so that it 
is kind of dependent on its host to complete its offering as a programming 
language, which means any Clojure compiler will need to provide a mechanism 
for IO. Those would always differ from Clojures to Clojures, so I don't 
think that's part of what makes Clojure Clojure.

What are others thoughts on this?

P.S.: There's no point to this thread, its mostly curiosity.

-- 
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: Navigators and lenses

2017-03-09 Thread Didier
At this point, I feel like dismissing your library outright. But I'd like to 
reconsider and believe that you just fumbled to express your true intents.

Maybe try a do over? I'd like to know... Did you research Specter? Did you 
research Haskell lenses and racket lenses? Did you spend 2 months thinking 
about this? What were your thoughts? What did you see as issues in all of them, 
why is your approach better, or what different kind of trade offs does it make? 
Why should I care about 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.


Re: Vars as global thread-locals?

2017-03-10 Thread Didier
Absolutly, Clojure embraces its host platform. Always feel free to use the Java 
features when they work best for your use case. 

But just to clarify, Java's ThreadLocal is an implementation of dynamic 
scoping. The scope is determined not by the source code, but by the runtime 
circumstances, in this case, the running Thread. While it's not the classic 
kind of dynamic scoping, it is still dynamic and not lexical. 

It differs from Clojure's dynamic scope in that, Clojure's scope is determined 
by the runtime stack plus the current thread.

Clojure relies on ThreadLocal for the per-thread scoping implementation, and it 
uses its own implementation for the runtime stack based scoping.

This means that if you want to re-enter a thread after having executed in its 
context before, and still have access to its previously bound ThreadLocal, you 
can only do it with a ThreadLocal. With Clojure's dynamic Vars, I don't think 
this is possible, since Clojure restores the previous binding when you exit 
from the thread. Now, be careful with this, I've seen lots of bugs in Java due 
to people not realizing that the binding is permanently attached to the thread, 
unless explicitly unbound, especially with the use of thread pools.

So I'd consider Clojure dynamic Vars safer to use in most cases, and still 
would recommend you use them instead of ThreadLocal most of the time. Unless 
what you want to do is attach state to the thread, dynamic Vars will probably 
be better and easier.

Just my 2 cents.

-- 
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: Vars as global thread-locals?

2017-03-21 Thread Didier
Right, except each thread gets its own binding. So it's not necessarily that 
you'll get the value of the last binding up the call stack. This will only be 
true if you are in the same thread also.

I'm not sure if we agree on the rest, but explain it differently or not. 
ThreadLocal is an object, and so is a Clojure Var. When I say Clojure Var, I 
don't mean a variable, but an instance of the class clojure.lang.Var.

So you have two classes, ThreadLocal and Var. Each one gives you variable like 
behaviour. You'll need a true variable to point to the instance of each, in 
Clojure you can attach a local symbol to it, or a global symbol, same in java. 
In both, you'll probably want to store the instance through a globally 
accessible name, like with def in Clojure or a static in Java. You don't have 
too, but I don't see the use case for a local reference to the ThreadLocal or 
the Var.

So up to now, there's no difference between the two. Now, where the difference 
appears, is in their specific features, when working with the instances 
themselves. The ThreadLocal scope values by thread, and so does the Var. The 
only difference is that in Clojure, you can not set and get as you like, you 
must do it through a binding block, which will set on entry and unset on exit. 
In Java, you have to manually unset, and most probably should, as you exit.

Then there's the details, like Vars have a default global scope value, while 
ThreadLocal has a default init method if you get before a set.

The access scope to the Var instance or the ThreadLocal instance is up to you, 
put it in a local or a global variable, neither prevents you from doing either. 
The scope of the values returned by Var and ThreadLocal are both Thread scope, 
with Clojure adding an extra binding scope to Var on top of it.

I think we're saying the same thing at this point. In practice, you can think 
of ThreadLocal as thread scoped variables, and Vars as binding block scoped 
variables per thread.

-- 
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: Startup time of standalone .jar executable

2017-03-21 Thread Didier
To answer your question, yes, ClojureScript startup times would be as fast 
as booting a shell command, a python script, etc.

To this end, you can use Planck like previously suggested, but I would 
recommend Lumo over it: https://github.com/anmonteiro/lumo

Lumo is a standalone ClojureScript interpreter, think of it as CPython for 
ClojureScript. It runs on Windows, Linux and MacOSX. The difference with 
Planck is that Lumo runs on Node.JS, while Planck runs on JavaScriptCore.

With lumo, you can use Node libraries from ClojureScript. It boots in 0.12 
second on average.

With all self-hosted ClojureScript, you will be limited to pure 
ClojureScript, so even a macro which uses java dependencies to transform 
code will not work in self-hosted ClojureScript, which mean some 
ClojureScript library don't work.

Alternatively, just compile your code to javascript with the Java 
ClojureScript compiler, and have them call into the JavaScript itself.

On Tuesday, 21 March 2017 11:31:33 UTC-7, Mark wrote:
>
> Depending what the processing is, ClojureScript could be a viable option.
> As I mentioned earlier, "planck" has fast start times.
>
> https://github.com/mfikes/planck
>
>
> On Tue, Mar 21, 2017 at 11:42 AM, Duncan McGreggor  > wrote:
>
>> Has the application owner defined an interface for long-running 
>> components? If not, maybe convince them to. Then they could just (.start 
>> yourCode) and then make whatever API calls you have defined, with zero 
>> start-up costs per-call from their side. 
>>
>> (This is what I do when integrating non-Clojure .jar files into Clojure 
>> applications -- I make them follow the Component[1] model and provide 
>> access to whatever connections, config, etc., they need via the Component 
>> library definitions.)
>>
>> For your particular case, there are some fun ways in which you can manage 
>> state and respond to API calls in a long-running, in-memory Clojure app (in 
>> particular, core.async), so this could be a real treat for you :-)
>>
>> Hth,
>>
>> d
>>
>> 
>> [1] https://github.com/stuartsierra/component
>>
>> On 21 March 2017 at 12:29, John Gabriele > 
>> wrote:
>>
>>> On Tuesday, March 21, 2017 at 11:24:20 AM UTC-4, Michael Lindon wrote:

 I wrote a collaborator some clojure code which I distributed to them as 
 a standalone jar file which they are executing with 

 java -jar mystandalone.jar

 The problem is that this executable is called a great many times in their 
 application and every time the 
 executable is called there is a java/clojure startup cost. In fact the 
 startup cost heavily domiantes the
 run time, whereas executing the code in a repl is almost instantaneous.

 How can I get around this? Would it be better to make a clojurescript 
 executable?


>>>
>>> One way around it might be to write your program as a separate service, 
>>> running on the same machine, with it listening for connections on a network 
>>> port.
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clo...@googlegroups.com 
>>> 
>>> Note that posts from new members are moderated - please be patient with 
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+u...@googlegroups.com 
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> --- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to clojure+u...@googlegroups.com .
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure"

Re: off-topic: stackof developer survey

2017-03-22 Thread Didier
As I understand it, the Most Love metric asks people who work with the language 
how happy they are with it.

So I find this metric very interesting. Clojure foes rank well in this, but it 
falls below a lot of others. I'd like to know why?

Why doesn't everyone who uses Clojure loves it?

I can see either because it's not everyone's cup of tea. Like a love it or you 
don't situation. Or it actually has pain points, and as a community we should 
try to address those. 

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


Can you extend a Java class, and add new fields and constructors to it?

2017-03-22 Thread Didier
Hi,

I'm trying to see if you can extend a Java class in Clojure, in a way that 
lets you add class members (fields) and new constructor methods.

I'm pretty sure you can not with reify, since that only works on interfaces 
and protocol, but I'm thinking there should be a way to do so with proxy 
maybe?

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.


How do I spec a nullary function?

2017-03-23 Thread Didier
I'm trying to fdef a function of no arguments, how would I go about it? I 
only want a spec for the return value basically?

-- 
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: off-topic: stackof developer survey

2017-03-25 Thread Didier
Is Clojure so great at AI, ML, NLP and concurrent programming?

It seems to me the libraries are lacking. I also know there's a race for 
performance, and it looks like CPU parallelization isn't even fast enough, so 
distributed or GPU based solutions are being built, which I'm also not sure 
Clojure offers much support 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.


Re: off-topic: stackof developer survey

2017-03-26 Thread Didier
All the uncomplicate libraries look really awesome. I'm going to give them 
a try out. I agree with you 100%, as a Community, we'll have to build more 
tools, write tutorials, add tests, etc., if we truly want Clojure to grow. 
Awesome job on those, I like their landing page, great description, good 
doc, very nice.

On Saturday, 25 March 2017 18:23:29 UTC-7, piast...@gmail.com wrote:
>
> > doesn't drive me mad, but it does puzzle ans annoy 
> > me.  puzzle: why is it?  not sure, personally.
>
> I've seen this pattern at the last 2 startups that I've worked at: 
>
> The startup hires a bunch of people as they graduate from college. They 
> are hired to do data analysis, typically on some kind of financial data 
> (these are the types of startups I've been at). These newly hired people 
> have a background in math and statistics. They learned programming by 
> accident, incidentally. They learned Python, because that was what was 
> recommended in all of the college classes that they took. Then they 
> graduate and start work at the startup, and when they need to program, they 
> do it in Python, because that is what they know. They are learning a great 
> deal, very fast, about the business world, and financial analysis; they 
> don't feel they have the time to learn about a new programming language. 
>
> Meanwhile, from the perspective of the startup, the history of their 
> decisions went like this: they had an idea, so they contracted with a team 
> in India to build the prototype -- the founding team had no one technical 
> on staff, so they went with the cheapest option, which was PHP. So the crew 
> in India builds a flawed prototype in PHP. The basic idea for the startup 
> was good, and they make some money, so after a year they hire a CTO, who 
> immediately wants to scrap the prototype and build solid, high quality 
> software. The decision is made to move away from PHP. But what should they 
> move toward? They are already hiring a large number of data analysts who 
> know Python, so the most obvious option is to hire more Python programmers, 
> and standardize the company around Python. 
>
> I've seen this pattern more than once. 
>
>
>
>
>
>
>
> On Friday, March 24, 2017 at 6:17:15 PM UTC-4, Gregg Reynolds wrote:
>>
>>
>>
>> On Mar 24, 2017 5:05 PM,  wrote:
>>
>>
>>
>> > This did get me thinking though. If the community *did* want to score 
>> highly 
>> > on some of these metrics, what would those be?
>>
>> I'll be happy so long as Clojure is the popular choice for doing the 
>> things where it's advantages should matter: machine learning, AI, NLP, 
>> concurrent programming. 
>>
>> It drives me crazy that Python is doing so well in all of the areas where 
>> Clojure should be winning. There are such beautiful libraries for working 
>> with vectors and matrices with Clojure, which should obviously help with 
>> NLP, yet people use Python instead. Likewise, so much of machine learning 
>> should be done as work in parallel, and Clojure makes that easy, yet Python 
>> is preferred. Drives me crazy. 
>>
>>
>> doesn't drive me mad, but it does puzzle ans annoy me.  puzzle: why is 
>> it?  not sure, personally.
>>
>>
>> These last few years I've been at a lot of NLP startups, and the choice 
>> of Python makes me sad. 
>>
>>
>>
>>
>> On Wednesday, March 22, 2017 at 7:17:10 PM UTC-4, Luke Burton wrote:
>>
>>>
>>> On Mar 22, 2017, at 2:26 PM, Gregg Reynolds  wrote:
>>>
>>> very interesting stuff, esp. the sociological bits:
>>>
>>> http://stackoverflow.com/insights/survey/2017
>>>
>>> sadly, clojure does not even rank in popularity.  but it's number 1 in 
>>> pay worldwide.  o sweet vengeance!
>>>
>>>
>>> Some fun reading in there, Clojure features a couple of times. It would 
>>> be fun to watch for spikes in traffic to Clojure related resources, because 
>>> I'm sure that landing "most highly paid" will cause a few people to sit up 
>>> and take notice.
>>>
>>> This did get me thinking though. If the community *did* want to score 
>>> highly on some of these metrics, what would those be? Or do none of them 
>>> adequately capture what is valued by the Clojure community?
>>>
>>> I think I'd claim that popularity is a terrible metric, even though it 
>>> can be gratifying to be popular. The fact that lots of people do a 
>>> particular thing doesn't mean that thing is inherently good, or worth 
>>> striving for. Some very popular things are bad lifestyle choices, like 
>>> smoking, a diet high in sugary foods, and writing JavaScript.
>>>
>>> Conversely some very, very good things can die from even the perception 
>>> of being unpopular. We often get people asking on the subreddit why they 
>>> find so many "abandoned" libraries in Clojure. The fact a piece of software 
>>> might have been written years ago, and still be perfectly usable, is such 
>>> an anomaly in more "popular" languages that people assume we've all curled 
>>> up and died. I recently had a project steered away from Clojure (suffic

Protocol support with spec?

2017-03-28 Thread Didier
I was wondering if protocols do or will be extended to support specs?

I'm thinking in the two following ways:

1) I can spec a protocol's functions so that whoever implements it has a better 
and more complete specification of how it should do so.

2) Protocols can dispatch based on the tagged entity of the first argument. So 
if I have a multi-spec for a map, it can be used as a record, in that I can 
have protocol implementations for each type of the specced map.

-- 
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: Compiling gen-class runs static initializers: workarounds, solutions?

2017-03-28 Thread Didier
In my experience, there's definitly still issues with static initializers, even 
in 1.8.

I'd recommend you go mixed Java for those use case.

-- 
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: Vars as global thread-locals?

2017-03-28 Thread Didier

>
> which brings up the limitation of implementing dynamically scoped vars 
> with ThreadLocal: It would be reasonable to expect that the bindings of 
> dynamic vars propagate to all code inside the same function, even if 
> executed by a different thread
>

This is not a limitation, this was done on purpose. Traditional dynamic 
vars are not thread safe and don't play well inside threaded environments. 
Clojure purposely restricted the scope to single threads. You can propagate 
it explicitly by using (bound-fn). Dynamic vars in Clojure were designed as 
a concurrency primitive, not as an implicit parameter, though it is fine to 
use them for that if you know what you are doing. You can see that from 
Rich Hickey's Clojure slides: https://i.imgur.com/jx2vtPb.png

A Clojure var is not only an object, it is a language construct. And when 
> you make it dynamic, you can bind and re-bind it with different values as 
> your functions are invoked within each other. This is something a 
> ThreadLocal can't do, and it makes the dynamic var a different kind of 
> beast, used for different purposes. A dynamic var emulates a local var that 
> you don't need to pass as a parameter to functions down the stack.
>

You don't need to make them dynamic to re-bind them. The symbol is 
immutably bound to the Var, so to allow re-binding of def in Clojure, all 
symbols are mapped to Vars instead of the value being defed, which are 
mutable data structures with thread safety features. The first thread 
safety feature is volatile access across threads of a root pointer with 
automatic deref. Volatile is needed to guarantee that as soon as you 
re-def, all access will see the new def and not the old. The second thread 
safety feature is thread isolated value overrides. This is useful when you 
don't need threads to cooperate on the same data, but you need all of them 
to have their own copy to work with. Each feature is optional. So if you 
only want thread isolation, you create a dynamic with no root. If you only 
want volatile root, you create a non dynamic var. If you want both, you can 
do that too.

So yes, it is not exactly like ThreadLocal, but I guess this is the biggest 
thing I disagree about, it's that for every use case Var can be used for, 
there is nothing wrong with using it, even if a ThreadLocal could also be 
used. In fact, I'd frown upon someone using ThreadLocal when Var would work.

Dynamic vars are required to be global in Clojure, because Clojure will 
> check that your symbols have been defined, but they wouldn't need to.


Dynamic vars are not required to be global in Clojure, you can use 
(with-local-vars) if you only need them to be local. I know it is a bit 
complicated to refer to their instance directly, and there's no constructor 
for them, only indirect ones like def and (with-local-vars), but they can 
be used as a simple instance if you want. You can refer to the instance by 
using (var). You can pass this instance around. You can create local 
versions of them. You can even call into their java constructor if you want 
more control on them, at which point, you can fine tune when to push and 
pop on them. Now, I don't advise you use them through their Java interface, 
but you can if you want.

This is not unimportant, and indicates that vars and ThreadLocals are meant 
> for different purposes. A ThreadLocal will guarantee a new, different value 
> for each thread. For Vars, you need to manually do that at thread creation, 
> and it may be tricky for threads that you don't create, if possible.
>

This I agree with, and that's the only use case I can think of where 
ThreadLocal would be better. Slight correction though, ThreadLocals won't 
guarantee that, but can be made too, by overriding their init method. By 
default they return null otherwise. Vars and ThreadLocal are meant to be 
tools in my opinion, and they overlap quite a bit in functionality, and 
where it overlaps, I see no reason to use ThreadLocal over Vars, especially 
when considering that in most cases, you'll put your ThreadLocal inside a 
Var when using it from Clojure.

Regression: The reason that I brought up this discussion is that I didn't 
> understand why clojure.tools.logging uses a dynamic var for enforcing the 
> use of a specific *logger-factory*. Does anybody have an explanation for 
> that?
>

This lets you override the factory used to create the logger if you need 
too, within a particular thread and binding block. I'm not sure when that 
would come in handy for tools.logging, but I assume it sometimes is.

By the way, as I revisit your initial question:

Clojure encourages avoiding the use of vars as global thread-local storage, 
> by restricting their use to dynamic binding only.
>

I can see now what you were asking. The "dynamic" part is the idea that the 
value is pushed and poped within entry and exit of a binding block. I doubt 
Clojure has anything against global thread-local storage, but it wanted to 
provi

Re: Protocol support with spec?

2017-03-29 Thread Didier
 | I don't understand what this one is.

I think I might be wishing specs were also types. In my head, I see as say, if 
I spec a vector as ::cart-items, I'd like to implement a protocol for 
::cart-items which will dispatch to the function handling ::cart-items, and if 
that didn't exist, it would go back to dispatching on the Java type.

I'm pretty sure this wouldn't be possible, because objects don't know what spec 
they belong too, so it couldn't be implemented. But, I thought at least for 
tagged maps, where one key of the map is a pseudo-type, and a multi-spec, where 
the spec defines which key contains the tag info, maybe if you extended the 
multi-spec with a protocol somehow protocols could be made to dispatch on the 
tag.

As I write this, I feel more and more like this isn't possible, since again, at 
runtime, nothing is known of the associated spec. But I thought I'd still ask.

-- 
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: escape characters to make a string literal

2017-03-29 Thread Didier
 | Also interesting, clojure's print methods will handle some escapes, but not 
others

I think that's just that \t is printed as \t. Like a tab shows up as \t. 
Whereas say a Unicode like \u1234 will show the character of it. You can seek 
that here:

(print (pr-str "foo\u0009bar"))
"foo\tbar"

Also, what is \001? I would have expected only the first 0 to be escaped. Is 
this a Java special escape syntax?

-- 
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: Protocol support with spec?

2017-03-29 Thread Didier

>
> multi-spec doesn't require you to use a key of a map - it's an arbitrary 
> function on arbitrary data, so it could leverage satisfies? or other 
> protocol functionality.
>

Oh, that's good to know, but I'm talking other way around. Where I can 
dispatch based on what the spec is for a given data-structure.

Like if I could do this:

(defprotocol Bar
  (bar [this]))

(s/def ::name string?)
(s/def ::id int?)
(s/def ::person (s/keys :req [::name]))
(s/def ::item (s/keys :req [::id]))

(extend ::person
Bar
{:bar (fn [this] (::name this))})

(extend ::item
Bar
{:bar (fn [this] (::id this))})

(bar {::name "John Doe"})
(bar {::id 1234})


On Wednesday, 29 March 2017 13:15:06 UTC-7, Alex Miller wrote:
>
> multi-spec doesn't require you to use a key of a map - it's an arbitrary 
> function on arbitrary data, so it could leverage satisfies? or other 
> protocol functionality.

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


Is it normal for exercise-fn to return examples that don't conform?

2017-03-29 Thread Didier
If you look at this example:

(defn wtv [in] (if (= 0 in) 0 10))
(s/fdef wtv
:args (s/cat :in int?)
:ret (s/and int? #(not= 0 %)))

(s/exercise-fn `wtv)
(s/conform `wtv (wtv 0))

You'll see that exercise gives you most of the time the following sample:

[(0) 0]

But this fails to conform:

=> (s/conform `wtv (wtv 0))

=> :clojure.spec/invalid


 Also, why does exercise give repeated samples? Shouldn't they be unique?

([(0) 0] 
 [(-1) 10] 
 [(0) 0] 
 [(-1) 10] 
 [(-2) 10] 
 [(2) 10] 
 [(0) 0] 
 [(-1) 10] 
 [(-2) 10] 
 [(0) 0]) 

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.


Re: Is it normal for exercise-fn to return examples that don't conform?

2017-04-02 Thread Didier

>
> Generated samples aren't unique.


Is there any reason why samples are not unique? Is this on purpose, or just 
an accidental consequence of the implementation?

Conform like this:
>
> (s/conform (:args (s/get-spec `wtv)) [0])
>
>
If I conform like that, it is not really conforming my function spec, just 
the argument spec. Like, I have the same issue if doing `(s/valid? `wtv 
(wtv 0))`. Basically, I want to understand the semantics of exercise-fn. 
Does it just call my function with input generated from the args spec, and 
does not care about return? I thought it was supposed to show you example 
of input which do make the spec valid.

Nevermind, the doc string answers this:

exercises the fn named by sym (a symbol) by applying it to
> n (default 10) generated samples of its args spec. When fspec is
> supplied its arg spec is used, and sym-or-f can be a fn.  Returns a
> sequence of tuples of [args ret].
>
>
On Sunday, 2 April 2017 03:55:19 UTC-7, Leon Grapenthin wrote:
>
> Generated samples aren't unique.
>
> Conform like this:
>
> (s/conform (:args (s/get-spec `wtv)) [0])
>
>
> On Thursday, March 30, 2017 at 2:55:35 AM UTC+2, Didier wrote:
>>
>> If you look at this example:
>>
>> (defn wtv [in] (if (= 0 in) 0 10))
>> (s/fdef wtv
>> :args (s/cat :in int?)
>> :ret (s/and int? #(not= 0 %)))
>>
>> (s/exercise-fn `wtv)
>> (s/conform `wtv (wtv 0))
>>
>> You'll see that exercise gives you most of the time the following sample:
>>
>> [(0) 0]
>>
>> But this fails to conform:
>>
>> => (s/conform `wtv (wtv 0))
>>
>> => :clojure.spec/invalid
>>
>>
>>  Also, why does exercise give repeated samples? Shouldn't they be unique?
>>
>> ([(0) 0] 
>>  [(-1) 10] 
>>  [(0) 0] 
>>  [(-1) 10] 
>>  [(-2) 10] 
>>  [(2) 10] 
>>  [(0) 0] 
>>  [(-1) 10] 
>>  [(-2) 10] 
>>  [(0) 0]) 
>>
>> 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.


Re: Is it normal for exercise-fn to return examples that don't conform?

2017-04-03 Thread Didier
Do you know why they are not unique? Was that on purpose or an accidental 
behaviour of the implementation?

-- 
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: Orchestra, complete instrumentation for clojure.spec

2017-04-06 Thread Didier
Looks good. May I ask, what kind of support are we looking at? Is this 
something you reasonably see being carried to the release of 1.9? Or was it 
more of an experiment?

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


Component and company with Spring?

2017-04-06 Thread Didier
Hey,

I'm looking into trying out one of the component libraries for Clojure such as 
Component, Mount, Integrant, etc.

Unfortunately, at my company, Spring is king, and a lot of spring beans exist 
that are shared across teams and I need to rely on them. So I'd need a 
framework that can integrate with Spring so I could depend on components from 
spring and Clojure and mix them up. 

Does anyone have experience with this? Is it possible? Is there one framework 
better suited for it then others?

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.


Re: ANN: Orchestra, complete instrumentation for clojure.spec

2017-04-06 Thread Didier
I think that answers my question. I just wanted an approximate idea of the 
kind of LTS this would have, before depending on it. I meant like if it 
would keep up with the changes to spec before release. So I'm glad to hear 
it will and possibly even beyond.

Thanks.

On Thursday, 6 April 2017 11:43:55 UTC-7, Jeaye wrote:
>
> On Thu, Apr 06, 2017 at 11:31:46AM -0700, Didier wrote: 
> > Looks good. May I ask, what kind of support are we looking at? Is this 
> something you reasonably see being carried to the release of 1.9? Or was it 
> more of an experiment? 
>
> I'm not entirely sure what you mean by "carried to the release of 1.9" 
> here. I don't expect that Alex, Rich, et al. will change their minds, 
> again, about clojure.spec's instrument validating :ret and :fn specs. As 
> such, I intend for Orchestra to exist up until, and well beyond, Clojure 
> 1.9. 
>
> Orchestra is an integral part of my workflow and likely the biggest 
> improvement to my Clojure toolchain, along with clojure.spec, in the past 
> few years. 
>
> Let me know if I can help any further. 
>

-- 
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: was Re: ANN: Orchestra, complete instrumentation for clojure.spec

2017-04-06 Thread Didier
It's different, yet related.

Static type systems and clojure.spec both try to prevent bugs. They're tools to 
help you write correct programs, the same way that a testing framework is. 
Neither of them will catch all your bugs unfortunately. 

Static type systems catches bugs where you would try to do an operation over a 
type which does not support it. Types are not very precise though, like it will 
catch 10/"123", but not 10/0, because the type isn't more precise then int. So 
int/int will be ok, but int/string will be caught at compile time as a bug.

The advantage of static type systems is that what they do catch, they will 
catch 100% of the time and they generally run pretty quickly.

Clojure.spec catches bugs where you'll try to do something on a value which 
isn't acceptable, as well as catch bugs where the relationship between the 
input and output values is wrong. So it can catch 10/0 and 10/"123". If a 
parameter was true and functionally that means the output should be false, but 
a bug causes it to be true instead, well it can also catch that.

The disadvantage of clojure.spec is that you cannot be sure it caught 100% of 
those bugs. It will catch some, but maybe not all. It will also be much slower 
to run.

Now, clojure.spec has one more trick up its sleeves. It can be used for static 
analyses on steroids. If you've ever used Find bugs in java, you know a little 
what I'm talking about. If you use Spectrum, it will try to catch some of those 
same bugs at compile time, and it could in theory be made to catch 100% of the 
bugs static type systems catch. Spectrum is new and not fully featured yet, but 
so is clojure.spec, so this is a possible future which you can have a taste for 
today. I recommend checking it out: https://github.com/arohner/spectrum

Alright, that's the part about catching bugs. Now there's more to it. Type 
declarations are normally helpful documentation too, and so is clojure.spec. 
Spec, once again, can be way more precise in documenting. Similarly, types can 
help tooling and error messages, so can spec.

Finally, spec also allows some things types don't even cover, such as parsing 
and validation of non typed data like json. Spec can parse a complex structure 
into an AST. It can also validate EDN, or json that was unmarshalled into 
clojure.

As time goes on, I'm sure someone will find other use cases for it too.

Hope this helps.

P.S.: Clojure also has a static type system called core.typed. It is not as 
widely used though, and has only one developer working on it. It also doesn't 
compare to the languages you listed, since it is a gradual type system, more 
inline with typescript, typed racket and hack.

-- 
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: was Re: ANN: Orchestra, complete instrumentation for clojure.spec

2017-04-07 Thread Didier
@Colin Yates

If spec is a DSL to describe invariants and the static typing of other 
languages are too, then it's not true that all static typing DSLs can express 
what the spec DSL can.

If you say, could I build spec in other languages, or can I put asserts in the 
code using the full languages, ya off course you can, but not without 
considerable effort. Similarly, you can add static typing to Clojure, but that 
also comes with considerable effort.

That's why people skip over this. Can I embed a haskell inside Clojure? I 
could. I could embed a Clojure inside Haskell too. But those are not a given 
feature provided to me for free as standard. 

So the discussion should center around what features I get for free. With spec, 
you get a very powerful description DSL, more powerful than most static typing 
ones. You get generative testing, parsing, validation, asserts and 
documentation. With static typing systems, you get a often less powerful 
description DSL, compile time type assertions, and documentation. 

-- 
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: was Re: ANN: Orchestra, complete instrumentation for clojure.spec

2017-04-07 Thread Didier
 | I think you missed my point, which is only "Spec is great as we have the 
power of Clojure" - sure, just don't forget you have the power of ANOther 
language in that language as well.

Hum, I've probably missed your point sorry, I'm still not following.

 | no, this will, or at least should, be caught. 10/0 is not an int, and typed 
"/' would reject 0 as an ill-typed denominator.

In most static type systems this will not be caught, because they don't have a 
fraction type. So this is actually a function that takes two number types, and 
0 is a number too, so it will type check, but throw an exception at runtime. 

-- 
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: was Re: ANN: Orchestra, complete instrumentation for clojure.spec

2017-04-07 Thread Didier

>
> I have longed for a statically compiled language with type inference with 
>> the simplicity and consistency of Clojure's syntax that also supports 
>> generative testing and works on the JVM but alas, I have not found one. 
>> Frege and PureScript both look interesting but I am unsure of Frege's 
>> longevity and PureScript's performance on the JVM's Javascript 
>> environment.
>
>
> Note that both of those options both suffer from very difficult interop - 
> PureScript will probably not have any at all since it will be expecting to 
> interop with JS, and Frege has some but it's clunky due to the type system 
> mismatch.
>
> Personally I long for a Kotlin/Clojure hybrid, to the point that I have 
> seriously considered trying to build one.
>

ShenLanguage <http://shenlanguage.org/> is maybe the closest thing from a 
fully typed Clojure on the JVM, though it also suffers from poor interop.

I'd like to suggest Fantom <http://fantom.org/>. I wish more people used 
it. It is a functional/oop, actor concurrent, inference typed, static with 
optional dynamic typing language with good interop that runs on top of the 
JVM, CLR and JavaScript. It has a lot of similarities with Clojure, like a 
strong support for data literals such as for maps and lists, looping is 
mostly done through higher order functions, it has a subset of its own 
language as a data declaration format, immutable by default, strong 
concurrency support using actors model, etc. It just needs some love. I 
find at its core, its got a better offering than Kotlin.

On Friday, 7 April 2017 20:34:34 UTC-7, Colin Fleming wrote:
>
> I have longed for a statically compiled language with type inference with 
>> the simplicity and consistency of Clojure's syntax that also supports 
>> generative testing and works on the JVM but alas, I have not found one. 
>> Frege and PureScript both look interesting but I am unsure of Frege's 
>> longevity and PureScript's performance on the JVM's Javascript 
>> environment.
>
>
> Note that both of those options both suffer from very difficult interop - 
> PureScript will probably not have any at all since it will be expecting to 
> interop with JS, and Frege has some but it's clunky due to the type system 
> mismatch.
>
> Personally I long for a Kotlin/Clojure hybrid, to the point that I have 
> seriously considered trying to build one.
>
> On 8 April 2017 at 14:57, Didier > wrote:
>
>>  | I think you missed my point, which is only "Spec is great as we have 
>> the power of Clojure" - sure, just don't forget you have the power of 
>> ANOther language in that language as well.
>>
>> Hum, I've probably missed your point sorry, I'm still not following.
>>
>>  | no, this will, or at least should, be caught. 10/0 is not an int, and 
>> typed "/' would reject 0 as an ill-typed denominator.
>>
>> In most static type systems this will not be caught, because they don't 
>> have a fraction type. So this is actually a function that takes two number 
>> types, and 0 is a number too, so it will type check, but throw an exception 
>> at runtime.
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to 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: was Re: ANN: Orchestra, complete instrumentation for clojure.spec

2017-04-08 Thread Didier
Sorry, I didn't mean fraction type, I meant fraction literal. 

All I can say is neither Java, Kotlin or Ceylon have a non zero type. Not sure 
about heck or frege.

Also, I was eventually leading to more than just the literal 10/0. If the zero 
in this division comes from another formula, or is dynamically calculated, you 
won't catch this statically even if you have a non zero type.

I don't know enough about dependent types, I think they could catch this, 
maybe, I'm unsure. I do know that none of the asked languages have them. I've 
also heard from more knowledgeable people that they're still very verbose and 
unpractical. 

-- 
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: was Re: ANN: Orchestra, complete instrumentation for clojure.spec

2017-04-08 Thread Didier
After a bit of digging, it appears that dependent types, at least the Liquid 
Haskell kind, could catch it, but could also miss it. If you've constrained 
everything very tightly, it would catch it, if not, it could miss it.

In this regard, generative testing could still end up being practically more 
useful.

Another thing is that dependent types (the Liquid Haskell kind), would also 
catch potential false positive.

I'll mention Spectrum for clojure.spec again, because it is essentially a 
dependently typed static type checker for Clojure. It suffers from not 
everything being specced in Clojure, but you'll find it can still catch quite a 
lot, including the division by zero error I've described. It is still in early 
stages, and doesn't work with all Clojure code bases, but I'd keep an eye open 
for it.

Reference: 
http://goto.ucsd.edu/~ucsdpl-blog/liquidtypes/2015/09/19/liquid-types/

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


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

2017-04-10 Thread Didier
I think this pattern is fine.

What specifically about it annoys you?

You could do it without records, but then you wouldn't be creating a type. Do 
you really need a type?

The advantage of types in Clojure are that they let you do polymorphic dispatch 
of them. So they are useful if you have one function which you want to reuse 
for many types.

In your case, I'm not seeing other records implementing the protocol. So it 
doesn't seem you need polymorphic dispatch on type. So maybe you can drop the 
protocol.

Records are useful if you need a map with guaranteed keys. Spec makes this 
feature less useful, because you can now spec a map and test that it always has 
the right keys when used. If you have a record, a fn that works over that 
record just needs to check the argument has the type of record, and it knows 
the keys exist. If you have a map instead, the fn would need to check the keys 
exist.

Records don't support unions, all keys must exist. In your case, you want 
unions, a map with keys x,y or z. So if you use a record, some keys will always 
have nil value. So, again, you might be better served by a map.

Recap. Protocols if you want a common interface accross multiple types. Records 
if you want to create a map with guaranteed keys, which will identify itself as 
a named java type.

Your spec can't really be made shorter, since they need custom gens.

If I was you, I'd experiment with functions over maps. One thing to consider is 
that specs are structural types, not nominal. So if you spec a map, it 
describes its structure. A function says I take a structure of that shape, if 
you give me anything that conforms, I can successfully do my job. The shape 
itself has no known runtime name.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Derefs broken after clojure.tools.namespace.repl/refresh

2017-04-10 Thread Didier
Hum, not sure why you would do this, but I'm guessing refresh goes in an 
infinite async loop. You keep reloading a namespace which creates a thread to 
reload itself.

I can't really explain why the symbol exists, but is not bound. I would have 
thought either the symbol would not exist, or the Var would contain the correct 
value.

-- 
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 Didier
I agree with James, here's what I'd 
do: https://gist.github.com/didibus/d0228ffad9b920c201410806b157ff10

The only downside, and why you might still want to use types (probably with 
deftype), is to prevent people from using standard functions like <,>,= 
etc. If you deftyped virtual-time, it could not accidentally be used like a 
normal number. Ideally, you'd extend the Java Comparable interface too.

On Monday, 10 April 2017 17:50:58 UTC-7, 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.


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

2017-04-10 Thread Didier
Here it is adapted to use a 
deftype: https://gist.github.com/didibus/2ccd608ed9d226039f944b02a10f9ad5

I gather from your solution that "orchestra" is not needed to spec :ret 
> types?
>

It is not. The return spec will be used during st/check. If you want the 
return spec to be validated outside of st/check though, than you need 
Orchestra.

I shall have to read up on deftype versus defrecord.
>

I recommend the clojure.org explanation: 
https://clojure.org/reference/datatypes#_deftype_and_defrecord
In a nutshell, deftype is a blank Java class, defrecord is an extended 
PersistentHashMap.

I am not sure why you need a VirtualTime, and what it will be doing, so I 
can't really comment on which solution is best. As James said, it appears 
you might be creating something that behaves the same way Double does? 
Double already has positive and negative infinity and NaN:

(/ 0.0 0.0) ; NaN
(* 99e 99e) ; Infinity
(* 99e -99e) ; -Infinity
(< Double/NEGATIVE_INFINITY Double/POSITIVE_INFINITY) ; true
(= Double/NEGATIVE_INFINITY Double/POSITIVE_INFINITY) ; false

I'd suggest, if you need Double, use Double. If you need something close to 
Double, and you can build on top of it, simpler to go with the style of my 
first gist. If you can't build on top of double, deftype is probably what 
you want.

On Monday, 10 April 2017 21:41:35 UTC-7, Brian Beckman wrote:
>
> Wow... that's a comprehensive solution, Didier :) Bravo! It's a good 
> lesson for s/fdef, which I haven't yet studied. I gather from your solution 
> that "orchestra" is not needed to spec :ret types?
>
> As to semantics, on the one hand, I can spec ::virtual-time as a light 
> overlay over Double and risk conflation of ordinary operators like < <= = 
> etc. On the other hand, I have several options for full protection. I shall 
> have to read up on deftype versus defrecord.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Derefs broken after clojure.tools.namespace.repl/refresh

2017-04-11 Thread Didier
Experimentation is good. This is indeed surprising. I think it shows that a 
good debugger would still sometime be useful in Clojure. I can't really explain 
what's happening. 

-- 
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: Derefs broken after clojure.tools.namespace.repl/refresh

2017-04-11 Thread Didier

>
> A good debugger is indeed extremely useful for Clojure - I use one every 
> day :-)
>

Am I living in the past? I thought Clojure didn't have a way to step 
through code interactively? 

On Tuesday, 11 April 2017 16:30:14 UTC-7, Colin Fleming wrote:
>
> A good debugger is indeed extremely useful for Clojure - I use one every 
> day :-)
>
> On 12 April 2017 at 05:29, Didier > wrote:
>
>> Experimentation is good. This is indeed surprising. I think it shows that 
>> a good debugger would still sometime be useful in Clojure. I can't really 
>> explain what's happening.
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to 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: Derefs broken after clojure.tools.namespace.repl/refresh

2017-04-11 Thread Didier
Awesome, time for me to try Cursive.

-- 
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: Derefs broken after clojure.tools.namespace.repl/refresh

2017-04-11 Thread Didier
@Colin If I understand correctly, if I buy the personal license I can use it 
for my own commercial projects, but I can also use it at my work, to work on 
their code base, as long as I'm the one using it. Is that correct? I probably 
can't convince work to buy into a bunch of licenses, but I'd love to have a 
debugger availaible to me, to make my life easier. 

-- 
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] graphql-clj 0.2.0

2017-04-24 Thread Didier
How does this compare to Lacinia?

On Monday, 24 April 2017 11:24:22 UTC-7, Lei wrote:
>
> graphql-clj is a Clojure library that provides GraphQL implementation.
>
> In this new version 0.2.0,  schema and query validator have been 
> completely rewritten for simplicity and robustness. APIs have simplified in 
> this new version as well.
>
> The github repository is: https://github.com/tendant/graphql-clj
>
> Any comments and advices are welcome!
>
> Cheers,
> Lei
>

-- 
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: clj-duckling

2017-06-12 Thread Didier
Hey, cool that you are doing this and continuing to maintain the Clojure 
variant.

-- 
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 a function to partially parallelize collection processing

2017-06-19 Thread Didier
So, if I understand correctly, you need to have one function sequentially and 
lazily split the stream, then you want each split to be sequentially processed, 
but you'd like different splits to be processed in parallel.

I think for splitting, you could use (reductions), and then you could (pmap) 
over 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.


Why does gen-class executes with *ns* bound to clojure.core?

2017-06-20 Thread Didier
Take this code:

(ns dda.main
  (:gen-class))

(defn -main [] (prn (ns-name *ns*)))


If you bootstrap this through clojure.main, such as what lein does, it will 
print the namespace as "user". But if you bootsrap it through the generated 
java main class, it will return "clojure.core".

My intuition would have assumed it would be running under "dda.main" as the 
*ns*, or at least under "user", since that's a common convention.

I'm curious to know why "clojure.core"?

-- 
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 gen-class executes with *ns* bound to clojure.core?

2017-06-20 Thread Didier
Especially given this:

(ns dda.main
  (:gen-class))

(def should-exist "Do I exist?")

(defn -main [] (prn (str should-exist \space (ns-name *ns*



The (def) is evaluated, since should-exist is found when -main is called 
from the generated class, but why isn't (ns) evaluated? Which should have 
changed *ns* to "dda.main".


On Tuesday, 20 June 2017 16:46:27 UTC-7, Didier wrote:
>
> Take this code:
>
> (ns dda.main
>   (:gen-class))
>
> (defn -main [] (prn (ns-name *ns*)))
>
>
> If you bootstrap this through clojure.main, such as what lein does, it 
> will print the namespace as "user". But if you bootsrap it through the 
> generated java main class, it will return "clojure.core".
>
> My intuition would have assumed it would be running under "dda.main" as 
> the *ns*, or at least under "user", since that's a common convention.
>
> I'm curious to know why "clojure.core"?
>

-- 
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 gen-class executes with *ns* bound to clojure.core?

2017-06-20 Thread Didier

>
> *ns* is a dynamic var, so it points to the current namespace when your 
> function is running. Most code doesn't switch into a target ns in order to 
> execute functions from it.
>

I understand that, and I understand most code does not switch into the 
target ns. But this is not most code, this is the code generated by the 
gen-class directive to bootstrap your -main method from java. Both lein and 
clojure.main bootstrap your main method from inside "user", but gen-class 
does so from inside "clojure.core".

So I want to know:

1) Why does the generated java class from gen-class has "clojure.core" as 
its current namespace?

2) Why doesn't the (ns) function inside my namespace change the current 
namespace?

Thanks


On Tuesday, 20 June 2017 17:25:30 UTC-7, Sean Corfield wrote:
>
> The “trick” I’ve adopted to get around this:
>
>  
>
> (def my-ns **ns**)
>
>  
>
> I stick that near the top of any file in which I want to refer to _*that*_ 
> namespace (as opposed to whatever the _*current*_ value of **ns** is 
> during evaluation, since it’s dynamic).
>
>  
>
> Sean Corfield -- (970) FOR-SEAN -- (904) 302-SEAN
> An Architect's View -- http://corfield.org/
>
> "If you're not annoying somebody, you're not really alive."
> -- Margaret Atwood
>
>  
>
> On 6/20/17, 4:46 PM, "Didier"  on 
> behalf of did...@gmail.com > wrote:
>
>  
>
> Take this code:
>
>  
>
> (ns dda.main
>
>   (:gen-class))
>
>  
>
> (defn -main [] (prn (ns-name *ns*)))
>
>  
>
>
> If you bootstrap this through clojure.main, such as what lein does, it 
> will print the namespace as "user". But if you bootsrap it through the 
> generated java main class, it will return "clojure.core".
>
>  
>
> My intuition would have assumed it would be running under "dda.main" as 
> the *ns*, or at least under "user", since that's a common convention.
>
>  
>
> I'm curious to know why "clojure.core"?
>
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com 
> Note that posts from new members are moderated - please be patient with 
> your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com 
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> --- 
> You received this message because you are subscribed to the Google Groups 
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to clojure+u...@googlegroups.com .
> For more options, visit https://groups.google.com/d/optout.
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to 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 a function to partially parallelize collection processing

2017-06-20 Thread Didier
Do you want something like this?

(ns dda.test)

(def test-infinite-lazy-seq (repeatedly
 (fn [] {:id (rand-int 2)
 :val (rand-int 10)})))

(def test-finite-seq [{:id 1 :val 1}
  {:id 1 :val 2}
  {:id 3 :val 1}])

(defn parallel-per
  [k seqf ls]
  (pmap #(map seqf %) (partition-by #(k %) ls)))

(take 10 (parallel-per :id
   (fn [m] (update m :val inc))
   test-infinite-lazy-seq))

(parallel-per :id
  (fn [m] (update m :val inc))
  test-finite-seq)


It handles your simple example, and can also handle infinite sequences 
lazily, since I assumed your Kinesis stream would be infinite and you want 
to process things as they come through.

Now this only parallelize groups that come through back to back. It is not 
possible to do a group by ":id" on an infinite sequence, so the only thing 
you could do better then this would be to chunk. So you could take in batch 
of 100 from the stream, then group-by on it, and parallelize each groups. I 
can try to write a solution for that too if you want.


On Tuesday, 20 June 2017 11:57:59 UTC-7, Tom Connors wrote:
>
> Great, I'll watch that video. Thanks again.
>

-- 
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 a function to partially parallelize collection processing

2017-06-20 Thread Didier
Here:

(ns dda.test)

(def test-infinite-lazy-seq (repeatedly
 (fn [] {:id (rand-int 2)
 :val (rand-int 10)})))

(def test-finite-seq [{:id 1 :val 1}
  {:id 1 :val 2}
  {:id 3 :val 1}])

(defn parallel-per
  [k seqf ls]
  (pmap #(map seqf %) (vals (group-by #(k %) ls

(defn get-next [x]
  "Your code to call Kinesis for the next x item would be here."
  (take x test-infinite-lazy-seq))

(def processed (atom []))
(dotimes [_ 3] ; This would be a doseq instead, or whatever you need it to 
be
  (swap! processed
 #(concat % (parallel-per :id
  (fn [m] (update m :val inc))
  (get-next 20)

(parallel-per :id
  (fn [m] (update m :val inc))
  test-finite-seq)


This is what you would do if you wanted to "chunk" it. You'd just use 
group-by instead of partition-by. The difference is that parallel-per would 
lose the ability to process infinite sequences, as it is now mostly eager, 
because group-by is eager. So you'd have to call it in some loop where each 
time to pass it the next chunk to parallel-per process.


On Tuesday, 20 June 2017 19:28:04 UTC-7, Didier wrote:
>
> Do you want something like this?
>
> (ns dda.test)
>
> (def test-infinite-lazy-seq (repeatedly
>  (fn [] {:id (rand-int 2)
>  :val (rand-int 10)})))
>
> (def test-finite-seq [{:id 1 :val 1}
>   {:id 1 :val 2}
>   {:id 3 :val 1}])
>
> (defn parallel-per
>   [k seqf ls]
>   (pmap #(map seqf %) (partition-by #(k %) ls)))
>
> (take 10 (parallel-per :id
>(fn [m] (update m :val inc))
>test-infinite-lazy-seq))
>
> (parallel-per :id
>   (fn [m] (update m :val inc))
>   test-finite-seq)
>
>
> It handles your simple example, and can also handle infinite sequences 
> lazily, since I assumed your Kinesis stream would be infinite and you want 
> to process things as they come through.
>
> Now this only parallelize groups that come through back to back. It is not 
> possible to do a group by ":id" on an infinite sequence, so the only thing 
> you could do better then this would be to chunk. So you could take in batch 
> of 100 from the stream, then group-by on it, and parallelize each groups. I 
> can try to write a solution for that too if you want.
>
>
> On Tuesday, 20 June 2017 11:57:59 UTC-7, Tom Connors wrote:
>>
>> Great, I'll watch that video. Thanks again.
>>
>

-- 
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 gen-class executes with *ns* bound to clojure.core?

2017-06-21 Thread Didier
That makes sense. Actually if you use Clojure's Java API and you require a 
namespace and invoke a Var, it will do the same, *ns* will just be clojure.core.

So I get it is simply because the last thing to set ns was RT.

One more question:

So I assume "load" would eval ns in my namespace, setting *ns* to dda.main, 
then it would run through the file, eval all forms, and finally it would reset 
*ns* to the previous value. Is that correct, or is there something about 
loading that's different?

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.


Re: Why does gen-class executes with *ns* bound to clojure.core?

2017-06-21 Thread Didier
I think I answered myself, looks like it does here:

try {
  Var.pushThreadBindings(
RT.mapUniqueKeys(CURRENT_NS, CURRENT_NS.
deref(),
  WARN_ON_REFLECTION, 
WARN_ON_REFLECTION.deref()
  ,RT.UNCHECKED_MATH, RT.
UNCHECKED_MATH.deref()));
   loaded = (loadClassForName(scriptbase.replace('/', '.
') + LOADER_SUFFIX) != null);
 }
  finally {
  Var.popThreadBindings();
   }


So now I understand, but I wonder if it makes sense. 99% of the time, it 
won't be an issue, but if you're doing anything with *ns*, you'll run into 
a situation where if you compile and bootstrap yourself through gen-class 
or clojure's java API, your code will not behave similar to when you're 
loaded at runtime or bootsraped through clojure.main or lein.

(ns dda.main
  (:gen-class))

(def should-exist "Do I exist?")

(defn -main []
  (in-ns 'other)
  (ns-name *ns*))

A bad example, but this code will work through lein, clojure.main, and when 
loaded from a REPL, but not when started from gen-class or Clojure's java 
API. Is there a good reason for the discrepancy? Shouldn't all methods to 
bootsrap your code start out with an equal initialization scheme? I would 
suggest that Clojure's java API (which I assume gen-class uses under the 
hood) should also initialize the common bindings and set the namespace to 
user. That way, all entry point always behave similarly.


On Wednesday, 21 June 2017 07:03:55 UTC-7, Didier wrote:
>
> That makes sense. Actually if you use Clojure's Java API and you require a 
> namespace and invoke a Var, it will do the same, *ns* will just be 
> clojure.core.
>
> So I get it is simply because the last thing to set ns was RT.
>
> One more question:
>
> So I assume "load" would eval ns in my namespace, setting *ns* to 
> dda.main, then it would run through the file, eval all forms, and finally 
> it would reset *ns* to the previous value. Is that correct, or is there 
> something about loading that's different?
>
> 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.


Re: Why does gen-class executes with *ns* bound to clojure.core?

2017-06-21 Thread Didier
Great breakdown.

1. "compile and bootstrap yourself through gen-class" means: you generate a 
> class and then invoke the main() method of that class
>

I'd go further then just calling main. So I mean you generate a class, and 
every function call from Java using the generated class should be executed 
as if it were executed through clojure.main, so with the bindings set and 
inside the user namespace.
 

> 2. "loaded at runtime" means: you (presumably) start the REPL, load a 
> namespace (either from a source file or a class file), then invoke the 
> -main function
>

Correct. It's the case of a non AOT compiled namespace being loaded from 
one of the many (load) functions of Clojure. Such as:

(load "dda/main")
(dda.main/-main)
 

> 3. "bootstrapped through clojure.main" means: you invoke clojure.main (a 
> compiled program provided with Clojure) with the -m arg specifying a 
> namespace. This will start the Clojure runtime, load the namespace, then 
> invoke the -main function
>

Correct.
 

> 4. "bootstrapped through lein" means: I assume this is "lein run" with a 
> :main set or "lein run -m" but I think lein supports specifying a namespace 
> or a function in a namespace or a class with a main() method. Depending 
> which of those you're doing, this is like similar to either #1 or #2 and 
> here lein is effectively doing similar work as #3.
>

Correct, yes internally lein delegates to clojure.main I believe.
 

> 5. There is a Clojure Java API (http://clojure.github.io/clojure/javadoc/), 
> but I'm not sure if you are actually referring to this or something else. 
> Doing so would basically mean going through that API to do the same thing 
> as #2. 
>

I am talking about that API. I believe it uses RT under the hood, and ends 
up doing the same thing that #1 does. So in my test, if you did:

IFn require = Clojure.var("dda.main", "-main");
require.invoke();

This will run inside "clojure.core", and will not have any of the default 
bindings set available.

I think if I were to restate your suggestion, I would say that a 
> genclass-compiled main entry point should initialize the Clojure runtime 
> and invoke the code in a binding as if it were being invoked from other 
> Clojure code. I can see some logic in that (although that then also affects 
> #3 and #4 as they go through this code too).
>

Ya, arguably, I wonder why the clojure runtime doesn't initialize the 
bindings and sets the namespace to 'user before delegating execution back 
to user code. If it did, then every invocation of Clojure from Java would 
always be bootstrapped in a similar way, and run under an equal context. 
Clojure.main wouldn't need to do it anymore.

But there might be a good reason for not doing that inside the clojure 
runtime. In which case, it still leaves open the question of should clojure 
invocations through a generated class, and invocations from the Clojure API 
mimic the bootstrapping of clojure.main?


P.S.: I also know that in practice, this has not caused that many issues, 
due to the fact that Clojure is now many years old, and I've never heard of 
other people complain about the discrepancies between generated classes and 
the clojure API versus clojure.main. So I don't think its a pressing issue, 
but I still feel it could be worth a thought.


On Wednesday, 21 June 2017 09:19:59 UTC-7, Alex Miller wrote:
>
>
>
> On Wednesday, June 21, 2017 at 9:42:00 AM UTC-5, Didier wrote:
>>
>> I think I answered myself, looks like it does here:
>>
>> try {
>>   Var.pushThreadBindings(
>> RT.mapUniqueKeys(CURRENT_NS, CURRENT_NS.
>> deref(),
>>   WARN_ON_REFLECTION, 
>> WARN_ON_REFLECTION.deref()
>>   ,RT.UNCHECKED_MATH, RT.
>> UNCHECKED_MATH.deref()));
>>loaded = (loadClassForName(scriptbase.replace('/', 
>> '.') + LOADER_SUFFIX) != null);
>>  }
>>   finally {
>>   Var.popThreadBindings();
>>}
>>
>>
>> So now I understand, but I wonder if it makes sense. 99% of the time, it 
>> won't be an issue, but if you're doing anything with *ns*, you'll run into 
>> a situation where if you compile and bootstrap yourself through gen-class 
>> or clojure's java API, your code will not behave similar to when you're 
>> loaded at runtime or bootsraped through clojure.main or lein.
>>
>
> It would be helpful to be clearer about what you mean with these different 
> cases as it

Re: Why does gen-class executes with *ns* bound to clojure.core?

2017-06-22 Thread Didier
I opened a Jira enhancement: https://dev.clojure.org/jira/browse/CLJ-2185

Hope I did a good job at it.

On Wednesday, 21 June 2017 18:58:26 UTC-7, Alex Miller wrote:
>
> Was just musing some more - the Clojure Java API was added pretty late 
> (~1.6 or 1.7). I wonder if
>
> 1) changing the Java Clojure API to ensure a certain binding context and
> 2) changing the main() method to invoke the Clojure function through the 
> Java Clojure API
>
> would be a good end game. Would need a lot more analysis.
>
> On Wednesday, June 21, 2017 at 8:52:48 PM UTC-5, Alex Miller wrote:
>>
>>
>>
>> On Wednesday, June 21, 2017 at 6:09:43 PM UTC-5, Didier wrote:
>>>
>>> Great breakdown.
>>>
>>> 1. "compile and bootstrap yourself through gen-class" means: you 
>>>> generate a class and then invoke the main() method of that class
>>>>
>>>
>>> I'd go further then just calling main. So I mean you generate a class, 
>>> and every function call from Java using the generated class should be 
>>> executed as if it were executed through clojure.main, so with the bindings 
>>> set and inside the user namespace.
>>>
>>
>> I do not think you should treat clojure.main as the gold standard. 
>> clojure.main is a helper program and it makes some choices that may or may 
>> not be what every program wants. There is nothing special about the "user" 
>> namespace for example. Other repls choose other things (pretty sure the 
>> boot repl uses boot.user example). Likewise, there's nothing special about 
>> the set of things clojure.main chooses to bind on startup - lein, boot, and 
>> other tools make different choices. If anything, I'd say #2 is what you 
>> should consider the most canonical case.
>>  
>>
>>>  
>>>
>>>> 2. "loaded at runtime" means: you (presumably) start the REPL, load a 
>>>> namespace (either from a source file or a class file), then invoke the 
>>>> -main function
>>>>
>>>
>>> Correct. It's the case of a non AOT compiled namespace being loaded from 
>>> one of the many (load) functions of Clojure. Such as:
>>>
>>> (load "dda/main")
>>> (dda.main/-main)
>>>  
>>>
>>>> 3. "bootstrapped through clojure.main" means: you invoke clojure.main 
>>>> (a compiled program provided with Clojure) with the -m arg specifying a 
>>>> namespace. This will start the Clojure runtime, load the namespace, then 
>>>> invoke the -main function
>>>>
>>>
>>> Correct.
>>>  
>>>
>>>> 4. "bootstrapped through lein" means: I assume this is "lein run" with 
>>>> a :main set or "lein run -m" but I think lein supports specifying a 
>>>> namespace or a function in a namespace or a class with a main() method. 
>>>> Depending which of those you're doing, this is like similar to either #1 
>>>> or 
>>>> #2 and here lein is effectively doing similar work as #3.
>>>>
>>>
>>> Correct, yes internally lein delegates to clojure.main I believe.
>>>
>>
>> No, I don't think lein uses clojure.main at all.
>>  
>>
>>>  
>>>
>>>> 5. There is a Clojure Java API (
>>>> http://clojure.github.io/clojure/javadoc/), but I'm not sure if you 
>>>> are actually referring to this or something else. Doing so would basically 
>>>> mean going through that API to do the same thing as #2. 
>>>>
>>>
>>> I am talking about that API. I believe it uses RT under the hood, and 
>>> ends up doing the same thing that #1 does. So in my test, if you did:
>>>
>>
>> This is actually the same as #2, not #1. It's not making an interop call, 
>> it's invoking a var function, just like any other Clojure call. 
>>
>>>
>>> IFn require = Clojure.var("dda.main", "-main");
>>> require.invoke();
>>>
>>> This will run inside "clojure.core", and will not have any of the 
>>> default bindings set available.
>>>
>>> I think if I were to restate your suggestion, I would say that a 
>>>> genclass-compiled main entry point should initialize the Clojure runtime 
>>>> and invoke the code in a binding as if it were being invoked from other 
>>>> Clojure code. I can see some logic in that (although that then also 
>&

Re: How to call Clojure from Java?

2017-06-26 Thread Didier
Using gen-class or the Clojure Java API like Daniel showed are the best 
ways I know of. If you want static types in Java and auto-complete, and 
things to feel like Java, use gen-class, if not, use the Clojure Java API.

On Saturday, 24 June 2017 12:05:55 UTC-7, thelmuth wrote:
>
> Thanks for the suggestions! Daniel's code helped me a lot, thanks!
>
> One thing that had me stuck for a while is that you have to have a Clojure 
> jar in your classpath. I also worked through a different way, using an 
> uberjar of a Clojure project. I posted my guides here 
> 
>  
> for anyone else trying to do this.
>
> On Thursday, June 1, 2017 at 10:11:25 PM UTC-4, Daniel Compton wrote:
>>
>> Hi thelmuth
>>
>> Here's a fully worked example. It calls the Clojure function 
>> myco.dashed-namespace.app.core/start!. Save it to 
>> src/myco/dashed_namespace/app/Main.java.
>>
>> package myco.dashed_namespace.app;
>>
>> import clojure.java.api.Clojure;
>> import clojure.lang.IFn;
>>
>> public class Main {
>> public static void main(String[] args) {
>> try {
>> IFn require = Clojure.var("clojure.core", "require");
>> require.invoke(Clojure.read("myco.dashed-namespace.app.core"));
>>
>> Clojure.var("myco.dashed-namespace.app.core", "start!").invoke();
>> }
>> catch (Throwable e) {
>> System.out.println(e.getMessage());
>> }
>> }
>> }
>>
>>
>> On Fri, Jun 2, 2017 at 1:24 PM James Reeves  
>> wrote:
>>
>>> 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  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 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 clo...@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with 
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+u...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> --- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to clojure+u...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to 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-29 Thread Didier
If you're no fan on emacs or vim, ProtoRepl is great. I also recommend cursive, 
but if you're no fan of intelliJ autosave, counterclockwise eclipse os 
surprisingly great. 

-- 
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: def partially done when used in if

2017-06-30 Thread Didier
I admit, this is very surprising. It looks like evaluation happens in two pass, 
like first it finds all defs and declares them, interning the symbol and 
creating an unbound var. And on a second pass it evaluates the full form.

Can someone more informed confirm or explain in more details what's responsible 
for this behavior?

-- 
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] New Canvas feature for Proto REPL Charts

2017-07-05 Thread Didier
I'm pretty sure you can just drag the pane out left and to the bottom to move 
it. And you can resize the height by hovering the mouse at the edge.

Those questions I think are best answered here: https://discuss.atom.io

-- 
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: [ClojureScript] [ANN] Orchestra 2017.07.04-1 (now supporting ClojureScript)

2017-07-10 Thread Didier
I find it funny that Clojure strongly believes that static types aren't worth 
the effort in most cases, but somehow the effort of adding generative testing 
is.

I think it's great to encourage people to use generative testing, but I'd 
rather it be à la carte, like most other things in Clojure. Orchestra allows 
that. If you want your :fn and :ret spec validated only on your manual tests, 
or on your regression tests, it lets you do that.

-- 
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: Evolve data / entities over time?

2017-07-10 Thread Didier
In Domain Driven Design, the domain model is the part which should be made 
to change the least, which is why getting is right is important, and more 
design time should go into it (often it receives the least amount of 
thought). The whole concept of DDD is based around this axiom, that 
changing your domain model will require to most compounding change, and 
should thus be minimized as much as possible.

The most common strategy is to scope things in sub-domains. So that each 
thing work with a data representation and model tailored to them, which 
only has what they need, in the shape that works best for them. Then, you 
map back and forth between their representation and your persistent one. So 
if you changed the persistent representation, you would only need to modify 
the mapping layer.

Another common strategy is to separate reads from writes in your domain. 
Design your domain model for writes. And for read, you just create a data 
fetching layer, which projects from the persistent write model into 
whatever read model you care about. If you need performance, you can add 
caching to those projections. The idea is that reads are cheap, in that 
they are trivial to refactor, while writes are hard, because invariants 
must be maintained, and the risk of corruption is real. So if you do that, 
you would less often need to change your domain model, basically only if 
you need to change the write requirement, but never when read requirements 
are changed.

Keep in mind that domain model is not= to data. That is, a domain 
encapsulates the data your business domain uses, the relationships between 
the data, and the behavior(as in the writes only) that the domain can do on 
that data. The best example is a SQL database schema. It contains the data 
of your domain, it describes the relationship between that data, and it 
generally protects against invariants, like does not allow you to delete a 
row without also deleting its foreign keys. Most often, you'll also have a 
layer in code to keep track of more complex invariants, like if you 
transfer money between two people, it should always reduce from one and add 
to the other equally, and never leave the state inconsistent. Given this, 
you would perform writes using your invariant keeping functions. So you 
might have a namespace for that. These functions could for example get the 
map, let you modify the map, and then update the map in the DB, but 
validate that it was changed in an acceptable way before doing so. Or you 
could have the functions to the update itself. Or a hybrid, where it 
returns a subset of the map to you only. And then you would also have 
another namespace to handle read projections, where you would ask for data 
in a specific format, and it would handle mapping it. Except from those 
reads, you are not able to write back.

On Monday, 10 July 2017 13:05:08 UTC-7, Luke Horton wrote:
>
> Per some recommendations on clojurians #clojure channel:
>
> - namespaced keys and addition over destruction
> - generally keep your data as flat as possible
> - finicky nested over "organized" data models are magnets for repeated 
> restructures into a new "better, more organized" structure
>
>
> On Monday, July 10, 2017 at 2:39:25 PM UTC-4, Luke Horton wrote:
>>
>> This is probably not clojure specific, but it’s a problem for which i’ve 
>> never really found a satisfying in other languages. Maybe clojure has a 
>> better opinion on the matter?
>>
>> How does one evolve/change data (entities) in a system over time without 
>> also having to change every piece that touches that data?
>>
>> e.g. if I had an entity “foo”:
>> {:a 'a
>>  :b 'b
>>  :c {:d 'd}}
>>
>> and I wrote a nice `clojure.spec` for that foo entity, and maybe 
>> formalized it into a record, anything that needed the data could read 
>> straight from built in functions:
>>
>> (get/get-in/... keyword)
>>
>> I could move one step more formal and write “accessors” for compound 
>> data, i.e. 
>>
>> (defn get-a-compound [foo] (str (:a foo) (:b foo) (get-in foo [:c :d])
>>
>> Now at some point I have to change my entity because a business 
>> requirement changed, or the domain model wasn’t correct the first time. 
>> Must now everything that touches foo and follows the clojure.spec 
>> "contract" of the data shape change?
>>
>> What’s the idiomatic clojure way to handle this? Is it a solved problem, 
>> or is this just a reality that everyone must suffer? 
>>
>> Do I write "getters" for every little piece and lose the :keyword 
>> function accessibility? This seems like data hiding, and smells bad. 
>> Do I leave the raw data alone, and write compound getters? How do 
>> protocols fit into this?
>>
>> In short: how does one prevent the shape of the data from bleeding into 
>> the system such that you can evolve your data over time?
>>
>> Any opinions, references, or discussion would be much appreciated.
>>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clo

[ANN] r4f-pro: IDE for visual ontology-based, rule-based and algorithm-based software development

2017-07-10 Thread Didier
I feel like I'm missing out on this. It sounds very cool, but I'm not sureI 
understand the use cases whereI should reach for it. Can you speak of what kind 
of use case you can use rete and r4j 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.


If Clojure is to blame for the majority of the startup time, why doesn't ClojureScript proportionally slow down the JavaScript startup time also?

2017-07-14 Thread Didier
This link: 
https://dev.clojure.org/display/design/Improving+Clojure+Start+Time says 
that the Java startup time is ~94 ms, while Clojure boot time is ~640 ms. 
That's a ~680% increase.

On my machine the java start time is: ~1042 ms, and the Clojure start time 
is around ~3108 ms. A ~298% increase.

When I time the startup time of lumo against node, I get ~1190 ms for node, 
and ~1523 ms for lumo. A ~128% increase only.

Does Clojure perform more initialization then ClojureScript? And would that 
explain the much higher overhead Clojure has on top of the JVM, versus 
ClojureScript?

-- 
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: Migrating nREPL out of Clojure Contrib

2017-07-18 Thread Didier
I'm not too familiar with the way contribs are managed, isn't tools.nrepl repo 
in github? Wouldn't the only step to contribute be to sign the CA and send a 
pull request of your changes?

-- 
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: Migrating nREPL out of Clojure Contrib

2017-07-19 Thread Didier
So do we have any idea of contributions are not made because of the CA or Jira?

I understand it's hard to estimate how many people were discouraged by this. 
Maybe it should be part of the Clojure survey nexr time. 

Were you ever discouraged to contribute to a Contrib lib because of Jira?

Were you ever discouraged to contribute to a Contrib lib because of the CA?

I feel like without more data into these, it's only speculative that changes to 
nRepl would result in more active contributions from the community. 

-- 
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: Migrating nREPL out of Clojure Contrib

2017-07-22 Thread Didier
> The contrib process is in place because some want it that way - it's very 
> deliberately by design and AFAICT unlikely to change.

Are you saying the contrib process is deliberatly made to be difficult for the 
community to contribute to it?

If so, maybe if it had more obvious tenets, I find its difficult as a user to 
understand what the contribs are for, who maintains them, what their status 
are, and how they differ to the standards library, or other community projects.

I can't contribute to OSS, because of my current employment, but as a non 
contributing Clojure user, I've always wondered how much I should rely on 
contribs, some of them seem quasi-abandonned, yet they appear more official, 
and it makes it hard for me to decide if I want to take a dependency on them or 
not.

In a way, an active project gives me more trust, and if taking nRepl out of 
contrib makes it more active, that's a good thing. Unless contrib libs come 
with any official support guarantees, or some form of stronger commitments?

-- 
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: printing self referential data?

2017-07-23 Thread Didier
I'm not sure I can fully help without you explaining more what you're 
doing. It sounds like you've got a collection or container type which has 
an implementation of print that loops over its elements, and calls print on 
them. So if you have a cycle, the print will go on forever until memory 
runs out.

If you're using a standard type, you might be able to limit *print-level* 
. Most Clojure 
collections will limit how deep they print based on the value of this 
global dynamic Var.

If you want a solution that prints the full graph starting from any node, 
you'll have to define a custom implementation of print-method 
 which does a traversal 
of the graph and stops at cycles. The traversal you'll need to implement 
yourself. Print-method is only there to allow you to override the function 
used to print, for a specific type.

You could also look into using an existing graph library, like Loom 
. I believe it will print itself properly 
already.


On Sunday, 23 July 2017 17:45:04 UTC-7, Rob Nikander wrote:
>
> I'm translating some code from an object oriented language to Clojure. I'm 
> a little confused about a tree structure I had where tree nodes have parent 
> and children properties, so the structure forms cycles. I used atoms for 
> those properties, so I could wire it all up. The code is clean and simple 
> and I'm happy with it, except ... the things don't print in the REPL. 
> (stack overflow)
>
> Are there any tricks to printing cyclical data structures in the REPL?  
>
> Rob
>

-- 
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: printing self referential data?

2017-07-29 Thread Didier

>
> Why does `alter-var-root` here seem to succeed, but have no effect?


What you want is:

(set! *print-level* 2)

But, this will not work 100% of the time, and sometimes you might want 
alter-var-root.

Here's the trick. *print-level* is a dynamic Var. Alter-var-root only 
changes the root value of a Var, it can not change a dynamically binded 
value:

(def ^:dynamic x "I am root!")
x ; => "I am root!"
(binding [x "I am dynamically binded!"] x) ; => "I am dynamically binded!"
(alter-var-root #'x (constantly "I've had my root altered!"))
x ; => "I've had my root altered!"
(binding [x "I am dynamically binded!"] x) ; => "I am dynamically binded!"

So where is *print-level* binded you ask? Well, that depends on how you 
bootstrapped Clojure. Most of the time, such as when using lein, or 
clojure.main, those things will wrap your entire code in a binding, and 
they will bind a certain number of default dynamic var such as 
*print-level*. You can see the code for clojure.main here: 
https://github.com/clojure/clojure/blob/master/src/clj/clojure/main.clj#L76

So in your case, you're probably bootstrapping Clojure using a mechanism 
that binds *print-level*, thus changing its root has no effect in your 
code, you have to change its binding, and the function to do that is set!.

On Monday, 24 July 2017 07:12:05 UTC-7, Rob Nikander wrote:
>
> I think in my case here the easiest thing will be to remove the cycles, 
> but still I'd like to understand a couple things...
>
> On Sunday, July 23, 2017 at 10:12:46 PM UTC-4, Didier wrote:
>>
>> I'm not sure I can fully help without you explaining more what you're 
>> doing. It sounds like you've got a collection or container type which has 
>> an implementation of print that loops over its elements, and calls print on 
>> them. So if you have a cycle, the print will go on forever until memory 
>> runs out.
>>
>
> My container type (the tree node) is simply the standard clojure map. 
>
> If you're using a standard type, you might be able to limit *print-level* 
>> <https://clojuredocs.org/clojure.core/*print-level*>. Most Clojure 
>> collections will limit how deep they print based on the value of this 
>> global dynamic Var.
>>
>
> Okay, *print-level* works but it looks like I have to call print myself. I 
> can't rely on the REPL to print it. 
>
> (binding [*print-level* 2] (println (find-route "/reports")))   ; okay
>
> Why does `alter-var-root` here seem to succeed, but have no effect?
>
> (alter-var-root #'*print-level* (constantly 2))
> => 2
> *print-level*
> => nil
> (find-route "/reports")
> stack overflow
>
>  
>

-- 
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: Unnamed Types - What Am I Doing Wrong?

2017-07-29 Thread Didier
I feel your pain, but you kinda shot yourself in the foot from the get go. 
What you did is the same as if you had decided to use a Java List 
to store your Account info.

I'd suggest you read over this: 
https://clojure.org/reference/datatypes#_why_have_both_deftype_and_defrecord

It explains the idiomatic way to deal with application domain information, 
such as Account, Employees, etc. Spoiler, use records, or at least a map.

Now having said that, given a project across many namespaces, you will 
still have some of the problems of not having type declarations. Like if a 
function takes the record, but the argument is not called account, but say 
x instead, you would need to dig back to understand what this operates on. 
Spec could change that though.

On Tuesday, 25 July 2017 18:52:41 UTC-7, Kevin Kleinfelter wrote:
>
> I ran into the 'refactoring an unnamed type' problem.  I'd like to know 
> how experienced Clojurists avoid it.
>
> I've got an account record/structure.  It has things like an account name, 
> account number, etc.  I started off storing it in a vector, because it had 
> just two elements.  Account name was (first v).  Account number was (second 
> v).  And that worked up to a point.  Over time, it has acquired enough 
> pieces and rules that I really need to change its implementation.  I need 
> to refactor it.
>
> When it was only a few hundred lines long, in a couple of files, I could 
> examine each line.  Now that it's a dozen files and several thousand lines, 
> I just don't have the attention span.
>
> In a language with named types, I could search for AccountRecord.  I 
> could thoroughly find all the places I used it and refactor it.  Or I could 
> change the name of the type to tAccountRecord, and the compiler would 
> identify all the places where I used it (with error messages).
>
> In an OO language, I'd be accessing all of its pieces via getters and 
> setters, and I wouldn't have to find all of the places where I used it, 
> because the implementation would be a black box.
>
> But in a language with unnamed types, it's just a vector and I've just got 
> first and second and nth to search for.  That's going to find lots of 
> irrelevant stuff.  It's enough to make me pine for Java and a refactoring 
> IDE.  =:-o
>
> So how do developers who work with un-typed (or un-named type) languages 
> avoid this sort of problem?  Or, failing to avoid it, how do they clean up 
> afterward?
> tnx
>
>

-- 
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: Unnamed Types - What Am I Doing Wrong?

2017-07-29 Thread Didier
> I thought there would be be many benefits to using records, particularly 
> around protocols but I haven't felt the loss.

I like having the constructor ready made, and the extra documentation they 
provide on which key it has. Though spec remediates the latter a bit.

Other then that, they're faster, but that's not why I use them.

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


[inheritable-var] A wrapper of InheritableThreadLocal to define thread-inheritable variable

2017-07-29 Thread Didier
InheritableThreadLocal is not safe to use with ThreadPools. And a lot of the 
Clojure parallel constructs rely on ThreadPools.

I'd recommend you rely on dynamic Vars instead and use bound-fn when you want 
child threads to inherit parent's bindings. 

If you knew this already, then I see no harm in using InheritableThreadLocal, 
but just be sure you understand its risk. In most cases, it is unsafe. 

-- 
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: [inheritable-var] A wrapper of InheritableThreadLocal to define thread-inheritable variable

2017-07-29 Thread Didier
Your doc says this doesn't work with dynamic binding:

(def ^:dynamic *foo* 5)
(defn adder
  [param]
  (+ *foo* param))
(binding [*foo* 10]
 (doseq [v (pmap adder (repeat 3 5))]
   (println v)))

But it does since Clojure 1.3. They added binding conveyance: 
https://github.com/clojure/clojure/blob/master/changes.md#234-binding-conveyance

This means that in Clojure 1.3+, when using dynamic binding and future, 
agent, pmap or core.async, child threads will inherit the bounded vars 
properly.

You might want to make that clear in your doc.

I also believe there's an issue with your library, this does not work:

(definheritable foo "Main thread.")
(inheritable-binding [foo "In thread inside future, running on Clojure 
ThreadPools."]
 @(future @foo))

It also doesn't seem to play nice with core.async, whereas dynamic vars do:

(let [chan (async/chan)]
  (inheritable-binding [foo "In chan Thread."]
   (async/go
(async/>! chan @foo))
   (async/ CompilerException java.lang.RuntimeException: Unable to resolve symbol: 
foo in this context

(def ^:dynamic bar "In main thread.")
(let [chan (async/chan)]
  (binding [bar "In chan Thread."]
   (async/go
(async/>! chan bar))
   (async/ "In chan Thread."



On Saturday, 29 July 2017 19:37:13 UTC-7, Jiacai Liu wrote:
>
> Thanks for your tips.
>
> I have updated my code to wrap TransmittableThreadLocal 
> <https://github.com/alibaba/transmittable-thread-local/blob/master/README-EN.md>,
>  an 
> enhanced version of InheritableThreadLocal, to solve threadpool problem.
>
> On Sunday, July 30, 2017 at 3:11:59 AM UTC+8, Didier wrote:
>>
>> InheritableThreadLocal is not safe to use with ThreadPools. And a lot of 
>> the Clojure parallel constructs rely on ThreadPools.
>>
>> I'd recommend you rely on dynamic Vars instead and use bound-fn when you 
>> want child threads to inherit parent's bindings. 
>>
>> If you knew this already, then I see no harm in using 
>> InheritableThreadLocal, but just be sure you understand its risk. In most 
>> cases, it is unsafe. 
>>
>>

-- 
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: [inheritable-var] A wrapper of InheritableThreadLocal to define thread-inheritable variable

2017-07-29 Thread Didier
For the core.async example, it was my mistake. Forgot to definheritable 
foo. The example does not return an exception, but "Main Thread", showing 
that the inheritable did not work. If using async/thread it does work 
though.



On Saturday, 29 July 2017 08:07:08 UTC-7, Jiacai Liu wrote:
>
> After digging into dynamic + binding doesn't work in multithread, I create 
> a simple wrap to define thread-inheritable var.
> Any suggestions(bugs) are welcome.
>
> https://github.com/jiacai2050/inheritable-var
>

-- 
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: [inheritable-var] A wrapper of InheritableThreadLocal to define thread-inheritable variable

2017-07-30 Thread Didier
I think it would be nice if inheritable-var would set! the future executor 
service on load, so the user doesn't have to. This way it will just work 
with future also. Just my 2 cent.

Here's how to reproduce the issue with core.async:

(let [t 1000]
  (dotimes [x t]
(let [foo (inheritable-var (constantly "Main"))
  chan (async/chan)]
  (inheritable-binding [foo "In chan Thread."]
   (async/go
(async/>! chan @foo))
   (let [res (async/
> For your first example, we should decorate the executor future use, see 
> TransmittableThreadLocal 
> doc 
> <https://github.com/alibaba/transmittable-thread-local/blob/master/README-EN.md#22-decorate-thread-pool>
>
> (let [foo (inheritable-var (constantly "Main"))]
>   (set! clojure.lang.Agent/soloExecutor (->inheritable 
> clojure.lang.Agent/soloExecutor))  (inheritable-binding [foo "In future 
> thread"]
>@(future @foo)))
>
> For core/async example, this should return In chan Thread, are you using 
> v0.1.3 ?
>
> (let [foo (inheritable-var (constantly "Main"))
>   chan (async/chan)]
>   (inheritable-binding [foo "In chan Thread."]
>(async/go
> (async/>! chan @foo))
>(async/
> I will add binding conveyance and usage to decorate executor when using 
> thread pool in my doc
>
> Many thanks. 👍
>
> On Sunday, July 30, 2017 at 1:28:46 PM UTC+8, Didier wrote:
>>
>> Your doc says this doesn't work with dynamic binding:
>>
>> (def ^:dynamic *foo* 5)
>> (defn adder
>>   [param]
>>   (+ *foo* param))
>> (binding [*foo* 10]
>>  (doseq [v (pmap adder (repeat 3 5))]
>>(println v)))
>>
>> But it does since Clojure 1.3. They added binding conveyance: 
>> https://github.com/clojure/clojure/blob/master/changes.md#234-binding-conveyance
>>
>> This means that in Clojure 1.3+, when using dynamic binding and future, 
>> agent, pmap or core.async, child threads will inherit the bounded vars 
>> properly.
>>
>> You might want to make that clear in your doc.
>>
>> I also believe there's an issue with your library, this does not work:
>>
>> (definheritable foo "Main thread.")
>> (inheritable-binding [foo "In thread inside future, running on Clojure 
>> ThreadPools."]
>>  @(future @foo))
>>
>> It also doesn't seem to play nice with core.async, whereas dynamic vars 
>> do:
>>
>> (let [chan (async/chan)]
>>   (inheritable-binding [foo "In chan Thread."]
>>(async/go
>> (async/>! chan @foo))
>>(async/> => CompilerException java.lang.RuntimeException: Unable to resolve 
>> symbol: foo in this context
>>
>> (def ^:dynamic bar "In main thread.")
>> (let [chan (async/chan)]
>>   (binding [bar "In chan Thread."]
>>(async/go
>> (async/>! chan bar))
>>(async/> => "In chan Thread."
>>
>>
>>
>> On Saturday, 29 July 2017 19:37:13 UTC-7, Jiacai Liu wrote:
>>>
>>> Thanks for your tips.
>>>
>>> I have updated my code to wrap TransmittableThreadLocal 
>>> <https://github.com/alibaba/transmittable-thread-local/blob/master/README-EN.md>,
>>>  an 
>>> enhanced version of InheritableThreadLocal, to solve threadpool problem.
>>>
>>> On Sunday, July 30, 2017 at 3:11:59 AM UTC+8, Didier wrote:
>>>>
>>>> InheritableThreadLocal is not safe to use with ThreadPools. And a lot 
>>>> of the Clojure parallel constructs rely on ThreadPools.
>>>>
>>>> I'd recommend you rely on dynamic Vars instead and use bound-fn when 
>>>> you want child threads to inherit parent's bindings. 
>>>>
>>>> If you knew this already, then I see no harm in using 
>>>> InheritableThreadLocal, but just be sure you understand its risk. In most 
>>>> cases, it is unsafe. 
>>>>
>>>>

-- 
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: Predicates for atom/ref/agent

2017-08-05 Thread Didier
ClojureScript portability is probably the best reason. The other one is 
usage in spec. They don't all need to go in core, but going in the standard 
lib would be nice, like clojure.type-predicates.

Even better if we had clojure.types. And it could have both predicates and 
types defined in it. So you'd find atom? and all others in it, but you'd 
also have atom-type. So when you implement a protocol for both clojure and 
clojurescript, you could use types from clojure.types as a way to make it 
work for both.

(extend-protocol wtv
  atom-type
  ...)

While this could be made a lib, since its primary usefulness is portability 
with other Clojure dialects, I think it makes more sense to have it bundled 
with Clojure.

On Saturday, 5 August 2017 04:04:01 UTC-7, Alex Baranosky wrote:
>
> Do we want a predicate for every interface? I, for one, DEFINITELY do not. 
> Just make some utils if you need to check for (instance? IAtom x) a lot in 
> your application. All such fns do is bloat clojure.core.
>
> On Sun, Jul 16, 2017 at 5:24 PM, Alex Miller  > wrote:
>
>> The decisions for volatile? vs other predicates were made at different 
>> times so I don't think there is necessarily any guiding design principle 
>> behind having one vs not having the other. I wrote the volatile addition, 
>> but I don't remember any of the details around why we included volatile? at 
>> that time.
>>
>> The broader question is, do we need a predicate for every interface? Is 
>> this worth having vs just #(instance? clojure.lang.IAtom %). One reason a 
>> predicate can be useful is for portability with ClojureScript, so I think 
>> that adds a little more weight to atom? (and none for ref? or agent?). 
>>
>> Another question is where this would be useful - what could do you 
>> envision where it's helpful to have it. If it's not common, then it's not 
>> worth having yet another function in core that needs to be loaded.
>>
>> And another question is how prevalent this function is "in the wild" 
>> either as a predicate or even more interestingly as something else. 
>> clojure.inspector and cider.nrepl actually have an atom? that is more of 
>> the traditional lisp/scheme sense of a non-collection. I see other impls of 
>> atom? in places like plumatic schema, taoensso encore, hara.common.checks, 
>> seesaw, and many others. (All of those impls are actually dated in that 
>> they check for the concrete class Atom rather than the interface IAtom that 
>> was introduced in 1.7.). See https://crossclj.info/clojure/atom%3F.html 
>> for more definitions. 
>>
>> Having many existing impls of this function out there means that we 
>> either introduce warnings, or worse we actually introduce a core function 
>> that has different semantics - there are many similar functions that 
>> instead check for Atom, and some that do something entirely different. 
>>
>> Weighing all this, I can't say that adding atom?, ref? (likely to have 
>> way more conflicts with different semantics), or agent? seems like a big 
>> win to me and is certainly not problem-free. When we added volatile?, that 
>> was not an existing overlap with many (or maybe any) existing functions out 
>> in the wild so was a little easier from that perspective.
>>
>> On Sunday, July 16, 2017 at 3:38:47 PM UTC-5, Shantanu Kumar wrote:
>>>
>>> Hi,
>>>
>>> Since Clojure 1.7 there's a `volatile?` predicate function, but no such 
>>> equivalent for atom/ref/agent. Can anybody explain the rationale behind the 
>>> difference? I found an old thread on a related topic (URL below) but would 
>>> like to know if there's an updated explanation.
>>> https://groups.google.com/forum/#!topic/clojure/mIJK3x_SUyM
>>>
>>>
>>> Shantanu
>>>
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> 
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com 
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and s

:gen-class method signature help

2017-08-06 Thread Didier
Can you try:

:methods [#^{:static true} [score [java.util.List java.util.List] 
java.util.List]]

This says your score function takes two List arguments and returns a list.

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


:gen-class method signature help

2017-08-06 Thread Didier
Also, you need to change the name of the "score" function in clojure to 
"-score". Yes, that's a dash prefixed to it. Unless you have configured 
gen-class to do differently using ":prefix".

-- 
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: :gen-class method signature help

2017-08-07 Thread Didier
Arrays in Clojure are different to Lists, and its probably why when you pass 
arrays to the score fn, that things don't work 100%.

If you can coerce those arrays to a java list it would probably work. You can 
do that in js, but if that doesn't work or seem easy, you could have your 
-score wrapper do it too.

To convert the 2d array do:

(mapv #(into [] %) the-array)

To convert the 1d array do:

(into [] the-array)

And to convert the return of score from a list back to an array do:

(to-array the-list) or (to-array-2d the-list-of-list)

-- 
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: beginning to learn Clojure after imperative programming my whole life

2017-08-10 Thread Didier
It did for me. It's that Clojure forced me to learn about and practice new ways 
to model problems and solution. For example, I'm much better at recursion and 
dynamic programming now. Now algorithmic problems are always hard, so there's a 
limit to how much better I got because of Clojure, but for solving business 
problem it helped a lot more in that it allows me to quickly experiment and 
iterate on my experiments at an unprecedented speed.

-- 
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 Didier
Keep in mind Clojure can be made as fast as Java, it is not by default. 
What it is by default is one of the fastest dynamic programming language.

On Sunday, 13 August 2017 11:46:31 UTC-7, Daniel Gerlach wrote:
>
> Thx,
>
> that was it :)
>
> I used the boxed int version ^Integer as a type hint, so it had not the 
> expected effect. 
> I also only "type hinted" the input function parameter not the return 
> value.
>
>
> Greeting 
>
> Daniel Gerlach
>
>
>
> On Sunday, August 13, 2017 at 2:28:13 PM UTC+2, James Reeves wrote:
>>
>> 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  
>> 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 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 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 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.


CHAMP an improvement on HAMT?

2017-08-14 Thread Didier
I think that paper is from 2015. Curious to hear what are people's thoughts as 
to why it didn't replace Clojure's HAMT. I wouldn't mind a free 3x performance 
boost and a reduced memory footprint. Is it just a matter of didn't have 
someone doing the work, or did it turn out that there was issues with CHAMP 
that would prevent Clojure's default core data structures from being migrated 
to 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.


Entity–component–system and Clojure

2017-08-15 Thread Didier
I recently stumbled upon the entity-component-system design pattern which 
is popular in game engine 
design: https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system, 
and really liked what I saw, thought it could be a good fit for Clojure.

Basically, it has three concepts:

1) Components are pure data grouped together as per a given domain. In a 
game engine that would be for example the 3D positional data related to 
positioning of objects in the 3D scene. So one component would be 
PositionComponent and it would have :X, :Y.

2) Entities are collections of Components with a unique ID.

3) Systems are processing functions that take an entity, transforming their 
components' data, or performing side effects from them.

Generally, in games, they inverse the entities, so instead of having 
entities contain components, they have components stored in an array with 
the index being the entity ID, and another array which contains the set of 
components for the entity at that index. All of this is kept track of by a 
world container.

(def world
  {:entities []
   :comp1 []
   :comp2 []
   ...})


So say you want to create an entity which is composed of comp1 and comp2, 
you would just add to the world :entities at index 0 a set #{:comp1 
:comp2}, and to the world :comp1 and :comp2 vectors at index 0 an initial 
component1 and component2 data structure. In games, for performance, they 
use a bitmask instead of a set for the entry of :entities.


I'm not sure this structure is necessary if trying to use the pattern not 
for game, but it doesn't hurt either I think.

What I like about this, is I'm thinking its possible to use it to do 
data-driven functional object modeling in Clojure. A problem I face, and I 
feel other faces in Clojure, is how do you model entities without OOP? I 
find this creates a kind of OO that is functional and data driven.

You would spec a bunch of component, they're pure data. Then you'd define 
systems (aka functions) which take an entity, and operate on the entity's 
components (aka its data). At first glance, this appears to just be OOP, 
but there's no inheritance here, and functions that operate or related data 
are decoupled from the data. Systems are implicitly mapped to components, 
based on what they work on. So you can extend all entities with more 
functionality easily. You can also create entities from components on the 
fly.

On second glance, I wonder what's different about this from just functions 
operating over data. I think its just a more rigid means to do so when you 
need the concept of entities. In a way, entities act as a class, in that 
they're a template of data. A system works over that template.

Has anyone experimented with this in Clojure?

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


  1   2   3   4   >