Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Alex Miller
Thanks! Great to hear positive benchmark results. I'd guess that if you did 
(count (distinct (map hash your-set))) you'd see that was a lot smaller than 
(count your-set) in 1.5.1 indicating hash collisions.

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


Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Alex Miller
I'd agree with all that. One place we've seen nil but not false become more 
prevalent lately is in core.async. Channels reserve special meaning for nil 
(closed) but false is a valid channel value. So if-some and when-some are 
particularly useful in go loops that take from a channel. There are a lot of 
async examples out there that incorrectly use if-let and when-let for this.

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


Re: [ANN]: Buddy 0.1.0-beta3: Authentication, Authorization & Signing library for Clojure.

2014-02-15 Thread bob
Good library!

On Monday, February 10, 2014 12:54:59 AM UTC+8, Andrey Antukh wrote:
>
> Hi!
>
> Buddy is an authentication, authorization and signing library for clojure, 
> designed with simplicity in mind.
>
> Features / Sub libraries:
> * Modular Authentication  (implemented using protocols).
> * Modular Authorization (with access rules)
> * Signing library.
> * Password hashers library.
>
> Is a still young library and any feedback / api improvement suggestions 
> are welcome.
>
> Github: https://github.com/niwibe/buddy
> Doc: http://niwibe.github.io/buddy/ 
>
> Greetings.
> Andrey
>
>
> -- 
> Andrey Antukh - Андрей Антух - > / <
> ni...@niwi.be >
> http://www.niwi.be 
> https://github.com/niwibe
>  

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


Example in Joy of Clojure, 2nd edition (MEAP)

2014-02-15 Thread Eric
Hi,

I'm reading the second edition of Joy of Clojure (the MEAP), and there is 
an example that I don't quite get, and I was hoping someone here could help 
me. It's in chapter 8, talking about macros. There is an example of a macro 
called def-watched, which prints a message each time the root binding of a 
var changes:

(defmacro def-watched [name & value]
  `(do
(def ~name ~@value)
(add-watch (var ~name)
:re-bind
(fn [~'key ~'r old# new#]
  (println old# " -> " new#)

I understand almost everything, but I don't see why we have to use ~'keyand 
~'r rather than simply key# and r#. As I understand it, the first option (
~'var-name) would be useful to capture an external var inside the macro, 
but I don't see the point of doing it here, especially since ~'key is 
defined in the parameter list, so that it would anyway hide any external 
var. Could someone please help me understand this?

Thank you in advance,

Eric

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


Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Andy-
inline
On Saturday, February 15, 2014 12:41:52 AM UTC-5, Mars0i wrote:
>
> Could someone clarify for me why "some?" as a name for not nil makes sense 
> at all in the first place?  Not criticizing.  I just don't understand what 
> existence or there being some of something has to do with nil.  
>
> Maybe I don't understand the intent of nil.  I came to Clojure from Common 
> Lisp.  nil is a weird beast in CL, but it's also a weird beast in Clojure.
>
> Is the idea that nil is supposed to be an empty structure, and empty? and 
> seq are too general?  But unlike nil in Common Lisp, nil in Clojure is not 
> an empty structure, even though (empty? nil) is true.  [], (), (lazy-seq), 
> #{}, and {} are empty structures.  Am I misunderstanding?
>

I *think* the idea to name it *some* is since nil often means "no value" 
(as already said by puzzler). This is also how Scala and F# name it:
http://en.wikipedia.org/wiki/Option_type

And the (some-> ..) macro has existed for a while which works the same so I 
think it makes a lot of sense to call it some? instead of non-nil?.

HTH

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


Re: java.jdbc 0.3.3 select query exception: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

2014-02-15 Thread edbond
Make sure your db is correct, 
see 
http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html#setting-up-a-data-source

Show your db and id values.

Best,
Eduard

On Saturday, February 15, 2014 5:55:35 AM UTC+2, The Dude (Abides) wrote:
>
> Hi, I'm writing some queries using java.jdbc 0.3.3 as follows:
>
> (defn get-member-url [id]
>   (jdbc/query  db ["SELECT * FROM members WHERE id = ? LIMIT 1" id]))
>
> However this results in an exception error:
>
> java.lang.ClassCastException
> clojure.lang.LazySeq cannot be cast to clojure.lang.IFn
>
> Not sure what I'm missing here. Db is postgres with [postgresql/postgresql 
> "9.1-901.jdbc4"] and have the require [clojure.java.jdbc :as jdbc] at top 
> of the model file.
>
> The above syntax is following the instructions here:
>
>
> http://clojure-doc.org/articles/ecosystem/java_jdbc/using_sql.html#reading-rows
>
> Any idea what I may be missing. I tried the row-fn and doall, but no dice 
> so far.
>
>

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


ANN: Clidget 0.2.0

2014-02-15 Thread James Henderson
Hi all,

I've just released a new version of
Clidget- a very
lightweight library similar to Om, that watches your application
state and re-renders your UI components when necessary.

0.2.0 is a significant performance upgrade over 0.1.0 due to better
batching of DOM updates - which means that Clidget is now
comparablein
performance to Om.

For those who haven't seen Clidget before:

   - Clidget has *one macro*, 'defwidget', which looks and behaves like
   'defn' - you take in *values* and return a real DOM element, like any
   other Clojure function. When you call it, pass it *atoms*, and Clidget
   will work out when the DOM element needs to be re-rendered. That's all
   there is to it!


   - You choose how to render the DOM element, how to respond to events and
   how to update the atoms. Clidget does *one thing* - figuring out when to
   update widgets - there are people far better than me at designing DOM
   templating libraries!


Useful links:

   - Github, Rationale and README
   - A more in-depth comparison to Om, Reagent and
React
   - Clidget 'Hello
world
   '
   - Contact Manager
Tutorial
(along
   the same lines as Om + Reagent's tutorials)
   - TodoMVC 
implementation


Feedback always welcome!

Cheers,

James (@jarohen )

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


Re: Clojure code for detecting overlap of 3d shapes (specifically tetrahedra)?

2014-02-15 Thread Karsten Schmidt
Hi Lee, I've already implemented the algorithm described in this paper
and it will be part of my upcoming geometry library. To not keep you
waiting for the release, I've extracted the relevant code and put up
here:

https://gist.github.com/postspectacular/9021724

I had quite a few problems to get this working reliably (even the
original C code). It turned out the algorithm expects the vertices of
the tetrahedra to be in a certain ordering or else produces wrong
results. I've removed this need and added a function which ensures
this expected ordering and in my tests it seems to work all now. Also,
since the original C version wasn't very friendly to the Clojure way,
I've implemented some of the functions in more Clojuresque way, which
actually makes the code much more legible, but also does a little bit
more work in some cases than the C version with its endless
quick-fail-if-statements... Most of it though is pretty much the same
and I've tried to make it as lazy as possible. Any improvements
++welcome though!

Hope that helps! K.

On 13 February 2014 23:02, Lee Spector  wrote:
>
> Can anyone point to Clojure code for detecting when two 3d shapes overlap, 
> when given the [x y z] vertices of the two shapes?
>
> The specific case I care about will always involve two regular tetrahedra 
> (each of which is specified by 4 vertices), which may allow for special 
> simplifications or efficiencies, but I'd be happy to have a more general 
> solution as long as it's not weirdly slow.
>
> I know that there are some sophisticated algorithms for doing this sort of 
> thing (e.g. [1]), but the the algorithms I've found aren't trivial and the 
> only source code I've found is pretty messy and would take some work to 
> translate (e.g. from C).
>
> And I figure that if anybody is doing 3d stuff in Clojure then the code for 
> this is probably floating around somewhere... but I haven't been able to find 
> it.
>
> Does anyone know of (or want to write :-) code for this?
>
> I guess that a Java solution would also be workable, if I the interop is 
> straightforward enough, but it'd be nicer to have a working algorithm in 
> Clojure.
>
> Thanks,
>
>  -Lee
>
> [1] Fast tetrahedron-tetrahedron overlap algorithm. F. Ganovelli, F. Ponchio 
> and C. Rocchini August 11, 2002. 
> http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=862BA3F999652E3B0BC1E7A6A3E04D49?doi=10.1.1.114.2540&rep=rep1&type=pdf
>
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to 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/groups/opt_out.



-- 
Karsten Schmidt
http://postspectacular.com | http://toxiclibs.org | http://toxi.co.uk

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


Re: Example in Joy of Clojure, 2nd edition (MEAP)

2014-02-15 Thread Jan Herich
Hello Eric,

You can rewrite this functionality with key# and r# instead of ~'key and 
~'r and it would work just as well, 
it's only not necessary to use unique symbols here, because you are not 
using them in the function body
anyway, so there is no danger of accidental var capture. 

To be honest, i would rather use underscore symbols (written as ~'_ inside 
macro definition) to indicate 
that i won't use any of the first two parameters in the function body. 

Dňa sobota, 15. februára 2014 9:32:48 UTC+1 Eric napísal(-a):
>
> Hi,
>
> I'm reading the second edition of Joy of Clojure (the MEAP), and there is 
> an example that I don't quite get, and I was hoping someone here could help 
> me. It's in chapter 8, talking about macros. There is an example of a macro 
> called def-watched, which prints a message each time the root binding of a 
> var changes:
>
> (defmacro def-watched [name & value]
>   `(do
> (def ~name ~@value)
> (add-watch (var ~name)
> :re-bind
> (fn [~'key ~'r old# new#]
>   (println old# " -> " new#)
>
> I understand almost everything, but I don't see why we have to use ~'keyand 
> ~'r rather than simply key# and r#. As I understand it, the first option (
> ~'var-name) would be useful to capture an external var inside the macro, 
> but I don't see the point of doing it here, especially since ~'key is 
> defined in the parameter list, so that it would anyway hide any external 
> var. Could someone please help me understand this?
>
> Thank you in advance,
>
> Eric
>

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


Re: CLJX & CLJS problem

2014-02-15 Thread Karsten Schmidt
Thank you all so much for the great insights & references! Thanks to
Chas' sample project I got it all working now, so expect a few new lib
releases soon! Cheers, K.

On 14 February 2014 11:00, Chas Emerick  wrote:
> I've added a sample.project.clj file to the cljx repo and pointed to it from
> the README.  I can see how the confusion may have gotten started due to a
> particular detail in the example configuration snippet that was in the
> README, which is also fixed.
>
> If someone wants to submit a patch so that `lein cljx sample` dumps that to
> stdout (similar to `lein cljsbuild sample`), I'd be interested in that.
>
> Thanks,
>
> - Chas
>
>
> On 02/14/2014 05:26 AM, Dave Della Costa wrote:
>>
>> Hi Chas, thanks for the clarification--it was definitely not clear to me
>> how this worked so I appreciate the explanation.
>>
>> Regarding the PR, I suppose the same points you brought up here are
>> relevant there, since I proposed including my (mistaken) notion of how
>> source-paths work for cljx-based libs in the documentation there.
>>
>> So really the problem is a lack of knowledge about how leiningen works
>> when packaging up a jar.  However, despite the fact that this
>> information is not cljx-specific, it may be useful simply to re-state
>> what you've described in this email somewhere in the cljx docs for
>> clueless folks like myself, since obvious it's not clear what is
>> necessary configuration and what isn't...or else just provide a pointer
>> to the relevant leiningen docs (if they exist).
>>
>> In any case, thanks!
>>
>> DD
>>
>> (2014/02/14 19:14), Chas Emerick wrote:
>>>
>>> This isn't really right.  :source-paths are for your _sources_, not a
>>> place to drop in whatever paths you want either on the classpath or
>>> included in jar files, etc.  Also, all generated content should go into
>>> `target/*`, so that `lein clean` will have its intended effect
>>> (eliminating all artifacts of previous build / project mgmt activities).
>>>
>>> (Some tools [definitely Counterclockwise, perhaps other IDE plugins as
>>> well?] also use the value of :source-paths to configure go-to-definition
>>> operations and such, so including non-source directories in
>>> :source-paths will generally yield undesirable effects there.)
>>>
>>> When it builds jars, Leiningen includes resources from :source-paths,
>>> :resource-paths, and :compile-path; the latter is almost never
>>> customized, and defaults to "target/classes".
>>>
>>> So, you should put your cljx sources in :source-paths.  You should have
>>> cljx generate transformation results into some directory under
>>> `target/`. If you want to redistribute the results, you should either
>>> generate cljx results into `target/classes`, or investigate Leiningen's
>>> (plethora of) options for customizing jar contents; see e.g.
>>>
>>> https://github.com/technomancy/leiningen/blob/stable/sample.project.clj#L331
>>>
>>>
>>> FWIW, that isn't cljx-specific at all; the same applies to Clojure
>>> sources that are being AOT-compiled, and with a tweak, to Java sources
>>> to be javac-compiled.
>>>
>>> cljsbuild produces *JavaScript* output, so its configuration is never
>>> going to be relevant to whether or not ClojureScript resources produced
>>> by cljx can be consumed by downstream projects.
>>>
>>> Dave, thanks for the PR; I'll reply separately to that on github.
>>>
>>> - Chas
>>>
>>> On 02/13/2014 10:06 PM, Dave Della Costa wrote:

 Hi Karsten,

 Strangely, I was doing the exact same thing as you yesterday and
 struggled for a bit until I found settings that work.

 I achieved success when I used the configuration from Cornice as a
 template:

 https://github.com/rkneufeld/cornice/blob/master/project.clj

 ...with one exception, my cljsbuild config contained only

 :cljsbuild {:builds [{:source-paths ["target/generated/cljs"]}]}

 vs. all the extra jar config and one not.  If I recall correctly, I was
 getting the "java.util.zip.ZipException: duplicate entry" you mention
 until I removed the extra settings in cljsbuild.

 Looking at your config I also suspect you want

> :source-paths ["src-cljs"]

 instead of

> :source-paths ["src-clj" "src-cljs"]

 in your cljsbuild config.

 However, when I leave the cljsbuild configuration out completely, it
 seems to have no bearing on whether or not I can use the generated cljs
 files when including the library in another project.  I suspect the
 ":jar true" setting is only relevant if you have strictly cljs files
 that need to be included--it seems like cljx has its own orthogonal
 build process which automatically includes cljs files in the jar file
 but I haven't dug into the code yet to confirm.  This is just based on
 testing what happens when I tweak config settings (Kevin or Chas please
 let me know if I'm off-base here).

 What does seem to make all t

Re: Clojure code for detecting overlap of 3d shapes (specifically tetrahedra)?

2014-02-15 Thread Lee Spector


On Feb 15, 2014, at 11:49 AM, Karsten Schmidt wrote:

> Hi Lee, I've already implemented the algorithm described in this paper
> and it will be part of my upcoming geometry library. To not keep you
> waiting for the release, I've extracted the relevant code and put up
> here:
> 
> https://gist.github.com/postspectacular/9021724

[etc]


Hi Karsten,

Wow! That is *extremely* helpful! Thank you so much. I will experiment with it 
as soon as I can and let you know if I run into any issues, but it looks like 
you've done a fantastic job here, and I'm really grateful that you've done the 
work and released this part early.

Thanks!!

 -Lee

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


ANN: ring-token-authentication. A ring middleware to authenticate API requests

2014-02-15 Thread Jason Stewart
I've just pushed the first version of ring-token-authentication, a Ring 
middleware to authenticate HTTP API requests.

Token authentication is a popular way to authenticate API requests over 
HTTP. A client sends a token in the Authorization header like so:

Authorization: Token token=notasecret

The token is then parsed from the authorization header and checked for 
authenticity on the server side.

This middleware aims to make it easy to add HTTP token authentication to 
your application, like it is in many other frameworks.


This is my first open source Clojure project, and I'm excited to share it 
with you.
Come check it out at https://github.com/jstewart/ring-token-authenticationor on 
clojars here: 
https://clojars.org/ring-token-authentication

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


Re: query on clojure maps / vectors

2014-02-15 Thread Alan Moore
As previously mentioned, datalog/datomic both work over in-memory data and 
are excellent libraries.

You might also consider a rule engine such as Clara:

https://github.com/rbrush/clara-rules

Depending on your requirements, particularly if you need to efficiently 
match data as it changes over time as opposed to a single-shot query, then 
a rule engine may be more or less appropriate. Clara also provides a 
single-shot query feature like datalog/datomic. Clara has an extensible 
"accumulator" feature that I don't believe is available in those other 
libraries (but I could be wrong...) It allows you to reason about the 
properties of a collection of things (e.g. count, max, min, avg, etc.)

You can think of a rule as a persistent query or view - it can produce new 
results (matches) as your data changes without having to re-query the 
entire dataset. You not only get the matched data elements but if you have 
more than one rule (or query), your rules/queries are optimized to the 
extent that they share sub-expressions due to the use of a (modified) RETE 
algorithm.

Aside: Fundamentally, RETE trades increases in memory usage to speed up 
matching and like any algorithm has some worst case scenarios you need to 
be mindful of (partial matches.) The RETE graph effectively acts as a set 
of indexes into your data that are optimized specifically for your 
rules/queries.

Also, Clara has built-in truth maintenance features that may be beneficial 
to your situation. YMMV.

Hope this helps.

Alan


On Thursday, February 13, 2014 5:27:58 PM UTC-8, t x wrote:
>
> Hi, 
>
> Preemptive: :-) 
>
>   * I'm not looking for datomic. 
>   * I'm also not looking for sqlkorma. 
>
>   * An "in-memory" data-log might be what I'm after. 
>
> Context: 
>
>   I'm reading: 
> http://code.kx.com/wiki/JB:QforMortals2/tables 
>
>   and it struck me -- why can't I view a clojure {vector,list} of maps 
> as a table? I.e.: 
>
>   [{:tag :animal :type :dog :age 2} 
>   {:tag :animal :type :cat :age 4}] 
>
>   then do queries on things like: 
>
> "get me all vector-indices of cats' of age >= 3" 
>
> Question: 
>
>   Is there a library (or even a blog post) about doing sql-like 
> querying on _in memory clojure data structures_ ? 
>
> 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/groups/opt_out.


Re: Example in Joy of Clojure, 2nd edition (MEAP)

2014-02-15 Thread Eric
Hi Jan,
 
OK, I get it, thanks a lot for your quick answer.
 
Eric

Le samedi 15 février 2014 17:49:57 UTC+1, Jan Herich a écrit :

> Hello Eric,
>
> You can rewrite this functionality with key# and r# instead of ~'key and 
> ~'r and it would work just as well, 
> it's only not necessary to use unique symbols here, because you are not 
> using them in the function body
> anyway, so there is no danger of accidental var capture. 
>
> To be honest, i would rather use underscore symbols (written as ~'_ inside 
> macro definition) to indicate 
> that i won't use any of the first two parameters in the function body. 
>
> Dňa sobota, 15. februára 2014 9:32:48 UTC+1 Eric napísal(-a):
>>
>> Hi,
>>
>> I'm reading the second edition of Joy of Clojure (the MEAP), and there is 
>> an example that I don't quite get, and I was hoping someone here could help 
>> me. It's in chapter 8, talking about macros. There is an example of a macro 
>> called def-watched, which prints a message each time the root binding of a 
>> var changes:
>>
>> (defmacro def-watched [name & value]
>>   `(do
>> (def ~name ~@value)
>> (add-watch (var ~name)
>> :re-bind
>> (fn [~'key ~'r old# new#]
>>   (println old# " -> " new#)
>>
>> I understand almost everything, but I don't see why we have to use ~'keyand 
>> ~'r rather than simply key# and r#. As I understand it, the first option 
>> (~'var-name) would be useful to capture an external var inside the 
>> macro, but I don't see the point of doing it here, especially since ~'keyis 
>> defined in the parameter list, so that it would anyway hide any external 
>> var. Could someone please help me understand this?
>>
>> Thank you in advance,
>>
>> Eric
>>
>

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


Re: ANN: Om 0.4.0

2014-02-15 Thread boz
Thanks David! 

I get this on a fresh clone (commit 
7327bcdc17a665d5fde66376bfef9aa2b21c675a)
   Compiling "examples/tests/main.js" failed.
   java.io.FileNotFoundException: examples/tests/src (No such file or 
directory)

$ mkdir examples/tests/src
and build again works fine. 

--- long version ---
bozs-mbp:~/dev/clojure/temp/om (master|169m) $ lein cljsbuild once
Compiling ClojureScript.
Compiling "script/tests.simple.js" from ["src" "test"]...
Successfully compiled "script/tests.simple.js" in 15.829 seconds.
Compiling "examples/hello/main.js" from ["src" "examples/hello/src"]...
Successfully compiled "examples/hello/main.js" in 4.091 seconds.
Compiling "examples/mouse/main.js" from ["src" "examples/mouse/src"]...
WARNING: No such namespace: goog.events.EventType at line 23 
examples/mouse/src/core.cljs
Successfully compiled "examples/mouse/main.js" in 6.781 seconds.
Compiling "examples/multiroot/main.js" from ["src" 
"examples/multiroot/src"]...
Successfully compiled "examples/multiroot/main.js" in 3.775 seconds.
Compiling "examples/counters/main.js" from ["src" 
"examples/counters/src"]...
Successfully compiled "examples/counters/main.js" in 5.824 seconds.
Compiling "examples/animation/main.js" from ["src" 
"examples/animation/src"]...
Successfully compiled "examples/animation/main.js" in 3.538 seconds.
Compiling "examples/shared/main.js" from ["src" "examples/shared/src"]...
Successfully compiled "examples/shared/main.js" in 3.533 seconds.
Compiling "examples/typeahead/main.js" from ["src" 
"examples/typeahead/src"]...
WARNING: Extending an existing JavaScript type - use a different symbol 
name instead of js/String e.g string at line 29 
examples/typeahead/src/core.cljs
WARNING: Extending an existing JavaScript type - use a different symbol 
name instead of js/Number e.g number at line 39 
examples/typeahead/src/core.cljs
Successfully compiled "examples/typeahead/main.js" in 3.577 seconds.
Compiling "examples/sortable/main.js" from ["src" 
"examples/sortable/src"]...
Successfully compiled "examples/sortable/main.js" in 5.916 seconds.
Compiling "examples/graft/main.js" from ["src" "examples/graft/src"]...
Successfully compiled "examples/graft/main.js" in 3.459 seconds.
Compiling "examples/tests/main.js" from ["src" "examples/tests/src"]...
Compiling "examples/tests/main.js" failed.
java.io.FileNotFoundException: examples/tests/src (No such file or 
directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:138)
at clojure.java.io$fn__8638.invoke(io.clj:233)
...
Subprocess failed
bozs-mbp:~/dev/clojure/temp/om (master|170m) $ mkdir examples/tests/src
bozs-mbp:~/dev/clojure/temp/om (master|171m) $ lein cljsbuild once 
Compiling ClojureScript.
Compiling "examples/tests/main.js" from ["src" "examples/tests/src"]...
Successfully compiled "examples/tests/main.js" in 7.81 seconds.

On Thursday, February 13, 2014 10:02:50 PM UTC-8, David Nolen wrote:
>
> Happy to announce a new release of Om. There are some breaking changes 
> mostly to make the API more uniform - om.core/root was needlessly different 
> from om.core/build.
>
> The biggest and most exciting change is the inclusion of the :tx-listen 
> option to om.core/root. This will setup a callback which will be invoked 
> whenever an app state transaction occurs. This function will receive a map 
> tx-data which will include the :path that changed, :old-value and 
> :new-value on that path, :new-state and :old-state which is the entire 
> application (useful for rollbacks), and :tag if one was provided by the 
> transact! / update! call.
>
> It's extremely powerful to make a subscribeable channel out of this and 
> share it over your entire application via om.core/root's :shared option. 
> This is exactly what the reusable om-sync component does http.://
> github.com/swannodette/om-sync.
>
> For a full list of changes, bug fixes, and enhancements:
>
> http://github.com/swannodette/om/blob/master/CHANGES.md
>
> Feedback welcome!
>
> David
>
>
>

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


Re: ANN: Om 0.4.0

2014-02-15 Thread David Nolen
You can build individual examples, "tests" can't be built - it's just a
dummy thing that I use when I need to quickly verify something.

David


On Sat, Feb 15, 2014 at 3:00 PM, boz  wrote:

> Thanks David!
>
> I get this on a fresh clone (commit
> 7327bcdc17a665d5fde66376bfef9aa2b21c675a)
>Compiling "examples/tests/main.js" failed.
>java.io.FileNotFoundException: examples/tests/src (No such file or
> directory)
>
> $ mkdir examples/tests/src
> and build again works fine.
>
> --- long version ---
> bozs-mbp:~/dev/clojure/temp/om (master|169m) $ lein cljsbuild once
> Compiling ClojureScript.
> Compiling "script/tests.simple.js" from ["src" "test"]...
> Successfully compiled "script/tests.simple.js" in 15.829 seconds.
> Compiling "examples/hello/main.js" from ["src" "examples/hello/src"]...
> Successfully compiled "examples/hello/main.js" in 4.091 seconds.
> Compiling "examples/mouse/main.js" from ["src" "examples/mouse/src"]...
> WARNING: No such namespace: goog.events.EventType at line 23
> examples/mouse/src/core.cljs
> Successfully compiled "examples/mouse/main.js" in 6.781 seconds.
> Compiling "examples/multiroot/main.js" from ["src"
> "examples/multiroot/src"]...
> Successfully compiled "examples/multiroot/main.js" in 3.775 seconds.
> Compiling "examples/counters/main.js" from ["src"
> "examples/counters/src"]...
> Successfully compiled "examples/counters/main.js" in 5.824 seconds.
> Compiling "examples/animation/main.js" from ["src"
> "examples/animation/src"]...
> Successfully compiled "examples/animation/main.js" in 3.538 seconds.
> Compiling "examples/shared/main.js" from ["src" "examples/shared/src"]...
> Successfully compiled "examples/shared/main.js" in 3.533 seconds.
> Compiling "examples/typeahead/main.js" from ["src"
> "examples/typeahead/src"]...
> WARNING: Extending an existing JavaScript type - use a different symbol
> name instead of js/String e.g string at line 29
> examples/typeahead/src/core.cljs
> WARNING: Extending an existing JavaScript type - use a different symbol
> name instead of js/Number e.g number at line 39
> examples/typeahead/src/core.cljs
> Successfully compiled "examples/typeahead/main.js" in 3.577 seconds.
> Compiling "examples/sortable/main.js" from ["src"
> "examples/sortable/src"]...
> Successfully compiled "examples/sortable/main.js" in 5.916 seconds.
> Compiling "examples/graft/main.js" from ["src" "examples/graft/src"]...
> Successfully compiled "examples/graft/main.js" in 3.459 seconds.
> Compiling "examples/tests/main.js" from ["src" "examples/tests/src"]...
> Compiling "examples/tests/main.js" failed.
> java.io.FileNotFoundException: examples/tests/src (No such file or
> directory)
> at java.io.FileInputStream.open(Native Method)
> at java.io.FileInputStream.(FileInputStream.java:138)
> at clojure.java.io$fn__8638.invoke(io.clj:233)
> ...
> Subprocess failed
> bozs-mbp:~/dev/clojure/temp/om (master|170m) $ mkdir examples/tests/src
> bozs-mbp:~/dev/clojure/temp/om (master|171m) $ lein cljsbuild once
> Compiling ClojureScript.
> Compiling "examples/tests/main.js" from ["src" "examples/tests/src"]...
> Successfully compiled "examples/tests/main.js" in 7.81 seconds.
>
> On Thursday, February 13, 2014 10:02:50 PM UTC-8, David Nolen wrote:
>>
>> Happy to announce a new release of Om. There are some breaking changes
>> mostly to make the API more uniform - om.core/root was needlessly different
>> from om.core/build.
>>
>> The biggest and most exciting change is the inclusion of the :tx-listen
>> option to om.core/root. This will setup a callback which will be invoked
>> whenever an app state transaction occurs. This function will receive a map
>> tx-data which will include the :path that changed, :old-value and
>> :new-value on that path, :new-state and :old-state which is the entire
>> application (useful for rollbacks), and :tag if one was provided by the
>> transact! / update! call.
>>
>> It's extremely powerful to make a subscribeable channel out of this and
>> share it over your entire application via om.core/root's :shared option.
>> This is exactly what the reusable om-sync component does http.://
>> github.com/swannodette/om-sync.
>>
>> For a full list of changes, bug fixes, and enhancements:
>>
>> http://github.com/swannodette/om/blob/master/CHANGES.md
>>
>> Feedback welcome!
>>
>> David
>>
>>
>>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to 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 

Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Mars0i
Thanks for all of the very helpful answers about nil and "some".  I 
understand now.  I'll add my voice to those who are bothered by the two 
distinct uses of "some" (some, some-fn vs some->, some->>, some?) bother 
me.  

I celebrate the semi-arbitrary quirkiness of function names in Common Lisp, 
but that's kind of perverse.  I celebrate more, and benefit from the 
rational systematicity of function names in Clojure.  I guess wouldn't be 
bothered by the two "some" concepts in Clojure if the language hadn't 
already exhibited such a high standard for function choices and names.  I 
am fairly new to Clojure, but the elegant design and naming is obviously a 
great part of the appeal of the language.  I have great respect for people 
who have been working with Clojure for a long time, and especially those 
who have designed and built the language, but "some" surprises me.

I understand that we don't want to break code that already uses the 
existing functions with "some" in their names, and there is a lot of code 
to break at this point.  But is there a possibility of providing new names 
and deprecating old ones for the sake of long term improvement?  In 1.5, 
there are two functions each with the two meanings.  Adding more functions 
without fixing the issue has the potential to exacerbate the problem by 
making it harder to abandon one use or the other of "some".  If adding to 
the not-nil family of "some" functions is preferable, maybe some and 
some-fn could be deprecated in favor of alternative names for the same 
functions.  Maybe that's too difficult at this point, though.

I keep thinking of something I once read by Bjarne Stroustrup suggesting 
that when he first introduced C++, his goal was to keep it simple and 
elegant.  I'm not seriously worried that Clojure will become a monstrosity 
like C++ or Common Lisp.  (I love CL, and others love C++, but that doesn't 
mean we can't be honest about their design flaws.)

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


Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Mars0i
Thank you for all of the very helpful answers about nil and "some".  I 
understand now.

I am *very* grateful to Rich Hickey and all of the other dedicated Clojure 
developers.  For what it's worth, I'll add my voice to those who are 
bothered by the two distinct uses of "some" (some, some-fn vs some->, 
some->>, some?) bother me. 

I celebrate the semi-arbitrary quirkiness of function names in Common Lisp, 
but that's kind of perverse.  I celebrate more, and benefit from the 
rational systematicity of function names in Clojure.  I guess wouldn't be 
bothered by the two "some" concepts in Clojure if the language hadn't 
already exhibited such a high standard for function choices and names.  I 
am fairly new to Clojure, but the elegant design and naming is obviously a 
great part of the appeal of the language.  I have great respect for people 
who have been working with Clojure for a long time, and especially those 
who have designed and built the language, but "some" surprises me.

I understand that we don't want to break code that already uses the 
existing functions with "some" in their names, and there is a lot of code 
to break at this point.  But is there a possibility of providing new names 
and deprecating old ones for the sake of long term improvement?  In 1.5, 
there are two functions each with the two meanings.  Adding more functions 
without fixing the issue has the potential to exacerbate the problem by 
making it harder to abandon one use or the other of "some".  If adding to 
the not-nil family of "some" functions is preferable, maybe some and 
some-fn could be deprecated in favor of alternative names for the same 
functions.  Maybe that's too difficult at this point, though.

(I keep thinking of something I once read by Bjarne Stroustrup suggesting 
that when he first introduced C++, his goal was to keep it simple and 
elegant.  I'm not seriously worried that Clojure will become a ... 
monstrosity (I say that affectionately) like Common Lisp, though.)

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


Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Mars0i
Thank you for all of the very helpful answers about nil and "some".  I 
understand now.

I am *very* grateful to Rich Hickey and all of the other dedicated Clojure 
developers.  For what it's worth, I'll add my voice to those who are 
bothered by the two distinct uses of "some" (some, some-fn vs some->, 
some->>, some?).

I celebrate the semi-arbitrary quirkiness of function names in Common Lisp, 
but that's kind of perverse.  I celebrate more, and benefit from the 
rational systematicity of function names in Clojure.  I guess wouldn't be 
bothered by the two "some" concepts in Clojure if the language hadn't 
already exhibited such a high standard for function choices and names.  I 
am fairly new to Clojure, but the elegant design and naming is obviously a 
great part of the appeal of the language.  I have great respect for people 
who have been working with Clojure for a long time, and especially those 
who have designed and built the language, but "some" surprises me.

I understand that we don't want to break code that already uses the 
existing functions with "some" in their names, and there is a lot of code 
to break at this point.  But is there a possibility of providing new names 
and deprecating old ones for the sake of long term improvement?  In 1.5, 
there are two functions each with the two meanings.  Adding more functions 
without fixing the issue has the potential to exacerbate the problem by 
making it harder to abandon one use or the other of "some".  If adding to 
the not-nil family of "some" functions is preferable, maybe some and 
some-fn could be deprecated in favor of alternative names for the same 
functions.  Maybe that's too difficult at this point, though.

(I keep thinking of something I once read by Bjarne Stroustrup suggesting 
that when he first introduced C++, his goal was to keep it simple and 
elegant.  I'm not seriously worried that Clojure will become a ... 
monstrosity (I say that affectionately) like Common Lisp, though.)


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


Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Alex Miller
truthy? = identity
falsey? = 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/groups/opt_out.


Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Joel Hodbrooks
That’s fair.

On February 15, 2014 at 1:02:43 PM, Alex Miller (a...@puredanger.com) wrote:

truthy? = identity  
falsey? = 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 a topic in the Google 
Groups "Clojure" group.  
To unsubscribe from this topic, visit 
https://groups.google.com/d/topic/clojure/tseJgAi3HC4/unsubscribe.  
To unsubscribe from this group and all its topics, send an email to 
clojure+unsubscr...@googlegroups.com.  
For more options, visit https://groups.google.com/groups/opt_out.  

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


Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Joel Hodbrooks
Actually, truthy? = boolean. 

Anyway, throw everything I said in the trash. :-) No more sleepy posts to the 
ML from me.
On February 15, 2014 at 1:02:43 PM, Alex Miller (a...@puredanger.com) wrote:

truthy? = identity  
falsey? = 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 a topic in the Google 
Groups "Clojure" group.  
To unsubscribe from this topic, visit 
https://groups.google.com/d/topic/clojure/tseJgAi3HC4/unsubscribe.  
To unsubscribe from this group and all its topics, send an email to 
clojure+unsubscr...@googlegroups.com.  
For more options, visit https://groups.google.com/groups/opt_out.  

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


Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Andy Fingerhut
Alex's suggestion is a good way to determine whether the 10k clj-tuples in
a set case is being sped up by the new hash function -- just look at the
variety of values of (hash x) for all x's in the set and see whether it is
significantly more unique hash values in 1.6.0-beta1 than with 1.5.1.

As for the 1-2ms slower, I am curious to know what percentage increase that
represents over Clojure 1.5.1?

I have some benchmark results on the wiki page below.  Look especially in
the column "Clojure 1.6.0 just after this
commiton
Jan 30 2014" near the bottom of the table for some speed comparisons
versus the first column labeled "Using Clojure 1.6.0-alpha3 hash (same as
Clojure 1.5.1)".

http://dev.clojure.org/display/design/Better+hashing

Andy


On Fri, Feb 14, 2014 at 11:00 PM, tcrayford  wrote:

> I ran clojure 1.6 through a benchmark suite (proprietary, but thought
> knowing about results might be interesting). Most of the benches were 1-2ms
> slower, but one (that involves pushing around 10k clj-tuples into a set)
> went from ~90ms to ~4ms. I'd guess that's the new hash stuff coming in, but
> either way, that speedup is super awesome!
>
> On Friday, 14 February 2014 19:04:09 UTC, Alex Miller wrote:
>>
>> Clojure 1.6.0-beta1 is now available.
>>
>> Try it via
>> - Download: http://central.maven.org/maven2/org/clojure/
>> clojure/1.6.0-beta1
>> - Leiningen: [org.clojure/clojure "1.6.0-beta1"]
>>
>> Highlights below or see the full change log here:
>> https://github.com/clojure/clojure/blob/master/changes.md
>>
>> We expect Clojure 1.6.0-beta1 to be close to a release candidate; no
>> other big changes are planned. Please give us your feedback and final
>> issues if you find them so we can do the final release!
>>
>> Clojure 1.6.0-beta1 has the following changes from 1.5.1:
>>
>> 1) Clojure now builds with Java SE 1.6 and emits bytecode requiring Java
>> SE 1.6 instead of Java SE 1.5. [CLJ-1268]
>>
>> 2) The following features are no longer marked "Alpha" in Clojure:
>>
>> * Watches - add-watch, remove-watch
>> * Transients - transient, persistent!, conj!, assoc!, dissoc!, pop!, disj!
>> * Exception data - ex-info, ex-data
>> * Promises - promise, deliver
>> * Records - defrecord
>> * Types - deftype
>> * Pretty-print tables - print-table
>>
>> 3) The clojure.java.api package provides a minimal interface to bootstrap
>> Clojure access from other JVM languages. Example:
>>
>> IFn map = Clojure.var("clojure.core", "map");
>> IFn inc = Clojure.var("clojure.core", "inc");
>> map.invoke(inc, Clojure.read("[1 2 3]"));
>>
>> 4) Map destructuring extended to support namespaced keys. [CLJ-1318]
>>
>> In the past, map destructuring with :keys and :syms would not work
>> with maps containing namespaced keys or symbols. The :keys and :syms
>> forms have been updated to allow them to match namespaced keys and
>> bind to a local variable based on the name.
>>
>> Examples:
>>
>> (let [m {:x/a 1, :y/b 2}
>>   {:keys [x/a y/b]} m]
>>   (+ a b))
>>
>> (let [m {'x/a 1, 'y/b 2}
>>   {:syms [x/a y/b]} m]
>>   (+ a b))
>>
>> Additionally, the :keys form can now take keywords instead of symbols.
>>  This provides support specifically for auto-resolved keywords:
>>
>> (let [m {::x 1}
>>   {:keys [::x]} m]
>>   x)
>>
>> 5) New "some" operations
>>
>> Many conditional functions rely on logical truth (where "falsey"
>> values are nil or false). Sometimes it is useful to have functions
>> that rely on "not nilness" instead. These functions have been added to
>> support these cases [CLJ-1343]:
>>
>> * some? - same as (not (nil? x))
>> * if-some - like if-let, but checks (not (nil? test)) instead of test
>> * when-some - like when-let, but checks (not (nil? test)) instead of test
>>
>> 6) Hashing overhaul
>>
>> The Clojure hash algorithms have changed for many primitives and
>> collections.
>> Read the changelog and http://clojure.org/data_structures#hash for more
>> detail
>> and if you are building external collections.
>>
>> In general, this change creates better hash codes (better bit dispersion,
>> fewer
>> collisions) to improve performance of hashed collections (maps and sets).
>> *NOTE:* One side effect may be that code currently relying on the
>> arbitrary order
>> of hashed elements in a collection (tests for example) may need to be
>> fixed.
>>
>> 7) Other new things
>>
>> * unsigned-bit-shift-right - Java's >>>
>> * clojure.test/test-vars - run a set of tests with fixtures
>>
>> 8) Printing enhancements
>>
>> * [CLJ-908](http://dev.clojure.org/jira/browse/CLJ-908)
>>   Print metadata for functions when *print-meta* is true and remove
>> errant space at beginning.
>> * [CLJ-937](http://dev.clojure.org/jira/browse/CLJ-937)
>>   pprint cl-format now supports E, F, and G formats for ratios.
>>
>> 9) Error messages
>>
>> * [CLJ-1248](http://dev.clojure.org/jira/browse/CLJ-1248)
>>   Print 

[ANN] chronos-client-clj 0.1.0, a Clojure client to the Chronos distributed network timer service

2014-02-15 Thread Robert Day
Hi all,

My team recently open-sourced its new distributed timer service, Chronos 
(https://github.com/Metaswitch/chronos). As this might be of interest to 
Clojurians, I've written a Clojure client library for it 
(https://github.com/rkday/chronos-client-clj).

We work on distributed high-scale telecoms switches in the cloud, and we're 
very focused on ensuring resilience when individual servers fail, by making 
them stateless, using distributed databases, and so on. One of the big problems 
we had to solve was timers - where you may have an event that needs to fire at 
a future point, and must fire even if the server that originally scheduled it 
has failed by then. (In our case, users registered for a five-minute period - 
with one of a cluster of servers handling that registration - and if those five 
minutes passed without the registration being refreshed, we needed to 
unregister them and send notifications of that to other servers.) Chronos is 
our attempt to solve that problem in general - allowing you to set an arbitrary 
HTTP callback to happen at some future point, and then distributing the storage 
of those timers over a cluster of nodes according to a client-provided 
replication factor, and giving certain guarantees about how those timers pop 
during net splits and outages - all over a fairly simple HTTP interface.

I thought the general concepts here - statelessness, distributed processing, 
breaking this complicated bit of function out into a separate service with a 
simple API - might appeal to other Clojurians. Hence this library.

The client library is fairly simple - it's all described in the README - though 
it assumes a bit of knowledge about Chronos so you might want to read 
https://github.com/Metaswitch/chronos/blob/dev/readme.md, 
https://github.com/Metaswitch/chronos/blob/dev/api.md and/or 
https://github.com/Metaswitch/chronos/blob/dev/clustering.md as well. If you 
want more information about our overall project, see 
http://www.projectclearwater.org/, but I'm afraid it's largely C++. (Chronos 
itself is written in C++, but as it's a service with a HTTP API you don't need 
to link to it or worry about the code).

The Github page has instructions for building Chronos from source 
(https://github.com/Metaswitch/chronos#development). We also have packages for 
Ubuntu 12.04 x86_64 (our standard server platform) available - add our 
repository following the instructions at 
https://github.com/Metaswitch/clearwater-docs/wiki/Manual-Install#wiki-project-clearwater,
 run "sudo apt-get update", then "sudo apt-get install chronos". It can be run 
just as "chronos" - there are no command-line-arguments.

I don't expect this to be useful to everyone - but I suspect that this is the 
sort of thing where, if you're working on the sort of niche where it's useful, 
then it's *really* useful. Let me know what you think!

Best,
Rob

P.S. The Clojars jar isn't signed - I'm away from my GPG key this weekend - but 
I'll publish a signed version soon.

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


Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Alex Baranosky
Great job on the new release guys :)

My one bit of feedback is that if-some and when-some behave like a let, but
don't include "let" in the name.  My guess is that this was chosen because
if-some-let and when-some-let are starting to get awkwardly long.


On Sat, Feb 15, 2014 at 2:32 PM, Andy Fingerhut wrote:

> Alex's suggestion is a good way to determine whether the 10k clj-tuples in
> a set case is being sped up by the new hash function -- just look at the
> variety of values of (hash x) for all x's in the set and see whether it is
> significantly more unique hash values in 1.6.0-beta1 than with 1.5.1.
>
> As for the 1-2ms slower, I am curious to know what percentage increase
> that represents over Clojure 1.5.1?
>
> I have some benchmark results on the wiki page below.  Look especially in
> the column "Clojure 1.6.0 just after this 
> commiton
>  Jan 30 2014" near the bottom of the table for some speed comparisons
> versus the first column labeled "Using Clojure 1.6.0-alpha3 hash (same as
> Clojure 1.5.1)".
>
> http://dev.clojure.org/display/design/Better+hashing
>
> Andy
>
>
> On Fri, Feb 14, 2014 at 11:00 PM, tcrayford  wrote:
>
>> I ran clojure 1.6 through a benchmark suite (proprietary, but thought
>> knowing about results might be interesting). Most of the benches were 1-2ms
>> slower, but one (that involves pushing around 10k clj-tuples into a set)
>> went from ~90ms to ~4ms. I'd guess that's the new hash stuff coming in, but
>> either way, that speedup is super awesome!
>>
>> On Friday, 14 February 2014 19:04:09 UTC, Alex Miller wrote:
>>>
>>> Clojure 1.6.0-beta1 is now available.
>>>
>>> Try it via
>>> - Download: http://central.maven.org/maven2/org/clojure/
>>> clojure/1.6.0-beta1
>>> - Leiningen: [org.clojure/clojure "1.6.0-beta1"]
>>>
>>> Highlights below or see the full change log here:
>>> https://github.com/clojure/clojure/blob/master/changes.md
>>>
>>> We expect Clojure 1.6.0-beta1 to be close to a release candidate; no
>>> other big changes are planned. Please give us your feedback and final
>>> issues if you find them so we can do the final release!
>>>
>>> Clojure 1.6.0-beta1 has the following changes from 1.5.1:
>>>
>>> 1) Clojure now builds with Java SE 1.6 and emits bytecode requiring Java
>>> SE 1.6 instead of Java SE 1.5. [CLJ-1268]
>>>
>>> 2) The following features are no longer marked "Alpha" in Clojure:
>>>
>>> * Watches - add-watch, remove-watch
>>> * Transients - transient, persistent!, conj!, assoc!, dissoc!, pop!,
>>> disj!
>>> * Exception data - ex-info, ex-data
>>> * Promises - promise, deliver
>>> * Records - defrecord
>>> * Types - deftype
>>> * Pretty-print tables - print-table
>>>
>>> 3) The clojure.java.api package provides a minimal interface to
>>> bootstrap
>>> Clojure access from other JVM languages. Example:
>>>
>>> IFn map = Clojure.var("clojure.core", "map");
>>> IFn inc = Clojure.var("clojure.core", "inc");
>>> map.invoke(inc, Clojure.read("[1 2 3]"));
>>>
>>> 4) Map destructuring extended to support namespaced keys. [CLJ-1318]
>>>
>>> In the past, map destructuring with :keys and :syms would not work
>>> with maps containing namespaced keys or symbols. The :keys and :syms
>>> forms have been updated to allow them to match namespaced keys and
>>> bind to a local variable based on the name.
>>>
>>> Examples:
>>>
>>> (let [m {:x/a 1, :y/b 2}
>>>   {:keys [x/a y/b]} m]
>>>   (+ a b))
>>>
>>> (let [m {'x/a 1, 'y/b 2}
>>>   {:syms [x/a y/b]} m]
>>>   (+ a b))
>>>
>>> Additionally, the :keys form can now take keywords instead of symbols.
>>>  This provides support specifically for auto-resolved keywords:
>>>
>>> (let [m {::x 1}
>>>   {:keys [::x]} m]
>>>   x)
>>>
>>> 5) New "some" operations
>>>
>>> Many conditional functions rely on logical truth (where "falsey"
>>> values are nil or false). Sometimes it is useful to have functions
>>> that rely on "not nilness" instead. These functions have been added to
>>> support these cases [CLJ-1343]:
>>>
>>> * some? - same as (not (nil? x))
>>> * if-some - like if-let, but checks (not (nil? test)) instead of test
>>> * when-some - like when-let, but checks (not (nil? test)) instead of test
>>>
>>> 6) Hashing overhaul
>>>
>>> The Clojure hash algorithms have changed for many primitives and
>>> collections.
>>> Read the changelog and http://clojure.org/data_structures#hash for more
>>> detail
>>> and if you are building external collections.
>>>
>>> In general, this change creates better hash codes (better bit
>>> dispersion, fewer
>>> collisions) to improve performance of hashed collections (maps and
>>> sets).
>>> *NOTE:* One side effect may be that code currently relying on the
>>> arbitrary order
>>> of hashed elements in a collection (tests for example) may need to be
>>> fixed.
>>>
>>> 7) Other new things
>>>
>>> * unsigned-bit-shift-right - Java's >>>
>>> * clojure.test/t

Re: ANN: ring-token-authentication. A ring middleware to authenticate API requests

2014-02-15 Thread Robert Day
On 15 Feb 2014, at 18:53, Jason Stewart wrote:

> I've just pushed the first version of ring-token-authentication, a Ring 
> middleware to authenticate HTTP API requests.
> 
> Token authentication is a popular way to authenticate API requests over HTTP. 
> A client sends a token in the Authorization header like so:
> 
> Authorization: Token token=notasecret
> 

Thanks! Not just because it's a useful library, but also because I hadn't come 
across Authorization: Token before - I've seen projects that use custom API 
headers for this, but I think this is a far cleaner approach.

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


fast parallel reduction into hash-set/map

2014-02-15 Thread Jules
Guys,

I've been playing with reducers on and off for a while but have been 
frustrated because they don't seem to fit a particular usecase that I have 
in mind... specifically: getting as many associations into a hash-map as as 
I can in as short a time as possible.

My understanding of the reason for this is that reducers practice a divide 
and conquer strategy. The incoming sequence is divided up. Each 
sub-sequence is reduced into a sub-result (possibly in parallel) and then 
the sub-results are combined into the the final outgoing result.

Unfortunately, there does not seem to be a better way of combining two 
hash-maps other than to read each entry from one and create a new 
corresponding association in the other. This means that each recombination 
in the above process essentially repeats most of the work already performed 
in the previous reduction stage.

Hash-sets are implemented via hash-maps, and simpler with which to 
demonstrate this problem:

user=> (def a (doall (range 1000)))
#'user/a
user=> (def b (doall (range 500 1500)))
#'user/b
user=> (time (def c (into #{} a)))
"Elapsed time: 6319.392669 msecs"
#'user/c
user=> (time (def d (into #{} b)))
"Elapsed time: 5389.805233 msecs"
#'user/d
user=> (time (def e (into c d)))
"Elapsed time: 8486.032191 msecs"
#'user/e


In the example above, you can see that the reduction into hash-sets of two 
overlapping lists of 10,000,000 elements takes 6.3 and 5.4 seconds. This 
stage can be carried out in parallel i.e. time elapsed for this stage would 
be 6.3 seconds - but we now have two hash-sets and we want one, so we have 
to combine them.


user=> (time (def e (into c d)))
"Elapsed time: 8486.032191 msecs"
#'user/e

As you can see, all the advantages of splitting the original sequence into 
2 and processing the two halves in parallel are lost since the 
recombination or their results takes 8.5 seconds - more than we saved by 
doing the reduction in parallel.

So, what can we do about it ?

I had a look at the code for PersistentHashMap (PersistentHashSet uses 
PersistantHashMap internally). I realised that it was possible to "splice" 
together the internal structure of two hash maps into a single one without 
repeating most of the work required to build one from scratch. So, I had a 
go at implementing it:


user=> (time (def f (clojure.lang.PersistentHashSet/splice c d)))
"Elapsed time: 3052.690911 msecs"
#'user/f

and:

user=> (= e f)
true

Whilst this is still adding 3 seconds to our time, that 3 seconds is half 
the time that we would have added had we executed the second reduction in 
serial, rather than in parallel.

This means that we can now reduce large datasets into sets/maps more 
quickly in parallel than we can in serial :-) As an added benefit, because 
splice reuses as much of the internal structure of both inputs as possible, 
it's impact in terms of heap consumption and churn is less - although I 
think that a full implementation might add some Java-side code complexity.

If you would like to give 'splice' a try out, you will need to clone my 
fork of clojure at github 

https://github.com/JulesGosnell/clojure

Please let me know if you try out the code. I would be interested to hear 
if people think it is worth pursuing.

I was also thinking that it should be possible to use a similar trick to 
quickly and cheaply split a map/set into [roughly] equal sized pieces 
(assuming an good hash distribution). This would enable the use of a 
map/set as an input sequence into the parallel reduction process outlined 
above. Currently, I believe that only a vector can be used in this way. It 
would be harder to arrange that 'count' could be implemented efficiently on 
these sub-maps/sets, but this is not important for the reduction process.

BTW - benchmarks were run on a 3.2ghz Phenom II / clojure/master / 
openjdk-1.7.0_51 / Fedora 20 with min and max 4gb ram.

regards,



Jules


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


Re: fast parallel reduction into hash-set/map

2014-02-15 Thread Alex Miller
You should try transients if you're looking to quickly fill collections - 
you might not even need to split up the work this way.


On Saturday, February 15, 2014 5:06:24 PM UTC-6, Jules wrote:
>
> Guys,
>
> I've been playing with reducers on and off for a while but have been 
> frustrated because they don't seem to fit a particular usecase that I have 
> in mind... specifically: getting as many associations into a hash-map as as 
> I can in as short a time as possible.
>
> My understanding of the reason for this is that reducers practice a divide 
> and conquer strategy. The incoming sequence is divided up. Each 
> sub-sequence is reduced into a sub-result (possibly in parallel) and then 
> the sub-results are combined into the the final outgoing result.
>
> Unfortunately, there does not seem to be a better way of combining two 
> hash-maps other than to read each entry from one and create a new 
> corresponding association in the other. This means that each recombination 
> in the above process essentially repeats most of the work already performed 
> in the previous reduction stage.
>
> Hash-sets are implemented via hash-maps, and simpler with which to 
> demonstrate this problem:
>
> user=> (def a (doall (range 1000)))
> #'user/a
> user=> (def b (doall (range 500 1500)))
> #'user/b
> user=> (time (def c (into #{} a)))
> "Elapsed time: 6319.392669 msecs"
> #'user/c
> user=> (time (def d (into #{} b)))
> "Elapsed time: 5389.805233 msecs"
> #'user/d
> user=> (time (def e (into c d)))
> "Elapsed time: 8486.032191 msecs"
> #'user/e
>
>
> In the example above, you can see that the reduction into hash-sets of two 
> overlapping lists of 10,000,000 elements takes 6.3 and 5.4 seconds. This 
> stage can be carried out in parallel i.e. time elapsed for this stage would 
> be 6.3 seconds - but we now have two hash-sets and we want one, so we have 
> to combine them.
>
>
> user=> (time (def e (into c d)))
> "Elapsed time: 8486.032191 msecs"
> #'user/e
>
> As you can see, all the advantages of splitting the original sequence into 
> 2 and processing the two halves in parallel are lost since the 
> recombination or their results takes 8.5 seconds - more than we saved by 
> doing the reduction in parallel.
>
> So, what can we do about it ?
>
> I had a look at the code for PersistentHashMap (PersistentHashSet uses 
> PersistantHashMap internally). I realised that it was possible to "splice" 
> together the internal structure of two hash maps into a single one without 
> repeating most of the work required to build one from scratch. So, I had a 
> go at implementing it:
>
>
> user=> (time (def f (clojure.lang.PersistentHashSet/splice c d)))
> "Elapsed time: 3052.690911 msecs"
> #'user/f
>
> and:
>
> user=> (= e f)
> true
>
> Whilst this is still adding 3 seconds to our time, that 3 seconds is half 
> the time that we would have added had we executed the second reduction in 
> serial, rather than in parallel.
>
> This means that we can now reduce large datasets into sets/maps more 
> quickly in parallel than we can in serial :-) As an added benefit, because 
> splice reuses as much of the internal structure of both inputs as possible, 
> it's impact in terms of heap consumption and churn is less - although I 
> think that a full implementation might add some Java-side code complexity.
>
> If you would like to give 'splice' a try out, you will need to clone my 
> fork of clojure at github 
>
> https://github.com/JulesGosnell/clojure
>
> Please let me know if you try out the code. I would be interested to hear 
> if people think it is worth pursuing.
>
> I was also thinking that it should be possible to use a similar trick to 
> quickly and cheaply split a map/set into [roughly] equal sized pieces 
> (assuming an good hash distribution). This would enable the use of a 
> map/set as an input sequence into the parallel reduction process outlined 
> above. Currently, I believe that only a vector can be used in this way. It 
> would be harder to arrange that 'count' could be implemented efficiently on 
> these sub-maps/sets, but this is not important for the reduction process.
>
> BTW - benchmarks were run on a 3.2ghz Phenom II / clojure/master / 
> openjdk-1.7.0_51 / Fedora 20 with min and max 4gb ram.
>
> regards,
>
>
>
> Jules
>
>
>

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

(series of swap! on atom) ==> single swap!

2014-02-15 Thread t x
Hi,

  Consider the following block of code:

## Sample Code

(ns test)


(def some-atom (atom {:tag :language
  :name "Clojure"
  :better-than ["scheme" "java" "ruby" "python"]}))


(defn demo-func []
  (swap! some-atom assoc-in [:name] "Clojure 1.6")
  (swap! some-atom assoc-in [:tag] :Language)
  (swap! some-atom update-in [:better-than] #(cons "javascript" %)))

;; I don't like the fact that things can happen between the swaps.

(defn what-I-want []
  (with-atom some-atom
assoc-in ...
assoc-in ...
update-in ...))

==> act as if a single
(swap! some-atom
    all changes here ...)


## Question

  Now, what I don't like above is that the swap! in the first example
can be interleaved with other swaps.

  Instead, I'd like all three swaps to happen all at once. Thus, I
need to do something like:

(swap! some-atom
  (fn [old]
... ))

but, notationally, this is messy compared to a series of swap!


Is there something like:

"with-atom ..."

which basically takes a series of changes, and puts them into a single
"swap! ... " ?

Thanks!

(I apologize if this question is not clear; and if so, please tell me
how I can make it more clear.)

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


Re: (series of swap! on atom) ==> single swap!

2014-02-15 Thread John D. Hume
On Sat, Feb 15, 2014 at 6:04 PM, t x  wrote:

>
> (defn what-I-want []
>   (with-atom some-atom
> assoc-in ...
> assoc-in ...
> update-in ...))
>

I often do something like this and don't find it too ugly:
(swap! my-atom #(-> %
  (assoc-in [:k] v)
  (update-in [:k2] inc)
  ,,,))

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


Re: fast parallel reduction into hash-set/map

2014-02-15 Thread Jules
from src/clj/clojure/core.clj:

(defn into
  "Returns a new coll consisting of to-coll with all of the items of
  from-coll conjoined."
  {:added "1.0"
   :static true}
  [to from]
  (if (instance? clojure.lang.IEditableCollection to)
(with-meta (persistent! (reduce conj! (transient to) from)) (meta to))
(reduce conj to from)))

Alex,

'into' does use transient - but as you can see from the code above, simply 
rebulds all the associations from one side into the other, whereas 'splice' 
interpolates the underlying tries building new trie nodes where 
appropriate. This makes it faster and more memory efficient as evidenced in 
the (into c d) vs (splice c d) timings above.

regards


Jules


On Saturday, 15 February 2014 23:52:00 UTC, Alex Miller wrote:
>
> You should try transients if you're looking to quickly fill collections - 
> you might not even need to split up the work this way.
>
>
> On Saturday, February 15, 2014 5:06:24 PM UTC-6, Jules wrote:
>>
>> Guys,
>>
>> I've been playing with reducers on and off for a while but have been 
>> frustrated because they don't seem to fit a particular usecase that I have 
>> in mind... specifically: getting as many associations into a hash-map as as 
>> I can in as short a time as possible.
>>
>> My understanding of the reason for this is that reducers practice a 
>> divide and conquer strategy. The incoming sequence is divided up. Each 
>> sub-sequence is reduced into a sub-result (possibly in parallel) and then 
>> the sub-results are combined into the the final outgoing result.
>>
>> Unfortunately, there does not seem to be a better way of combining two 
>> hash-maps other than to read each entry from one and create a new 
>> corresponding association in the other. This means that each recombination 
>> in the above process essentially repeats most of the work already performed 
>> in the previous reduction stage.
>>
>> Hash-sets are implemented via hash-maps, and simpler with which to 
>> demonstrate this problem:
>>
>> user=> (def a (doall (range 1000)))
>> #'user/a
>> user=> (def b (doall (range 500 1500)))
>> #'user/b
>> user=> (time (def c (into #{} a)))
>> "Elapsed time: 6319.392669 msecs"
>> #'user/c
>> user=> (time (def d (into #{} b)))
>> "Elapsed time: 5389.805233 msecs"
>> #'user/d
>> user=> (time (def e (into c d)))
>> "Elapsed time: 8486.032191 msecs"
>> #'user/e
>>
>>
>> In the example above, you can see that the reduction into hash-sets of 
>> two overlapping lists of 10,000,000 elements takes 6.3 and 5.4 seconds. 
>> This stage can be carried out in parallel i.e. time elapsed for this stage 
>> would be 6.3 seconds - but we now have two hash-sets and we want one, so we 
>> have to combine them.
>>
>>
>> user=> (time (def e (into c d)))
>> "Elapsed time: 8486.032191 msecs"
>> #'user/e
>>
>> As you can see, all the advantages of splitting the original sequence 
>> into 2 and processing the two halves in parallel are lost since the 
>> recombination or their results takes 8.5 seconds - more than we saved by 
>> doing the reduction in parallel.
>>
>> So, what can we do about it ?
>>
>> I had a look at the code for PersistentHashMap (PersistentHashSet uses 
>> PersistantHashMap internally). I realised that it was possible to "splice" 
>> together the internal structure of two hash maps into a single one without 
>> repeating most of the work required to build one from scratch. So, I had a 
>> go at implementing it:
>>
>>
>> user=> (time (def f (clojure.lang.PersistentHashSet/splice c d)))
>> "Elapsed time: 3052.690911 msecs"
>> #'user/f
>>
>> and:
>>
>> user=> (= e f)
>> true
>>
>> Whilst this is still adding 3 seconds to our time, that 3 seconds is half 
>> the time that we would have added had we executed the second reduction in 
>> serial, rather than in parallel.
>>
>> This means that we can now reduce large datasets into sets/maps more 
>> quickly in parallel than we can in serial :-) As an added benefit, because 
>> splice reuses as much of the internal structure of both inputs as possible, 
>> it's impact in terms of heap consumption and churn is less - although I 
>> think that a full implementation might add some Java-side code complexity.
>>
>> If you would like to give 'splice' a try out, you will need to clone my 
>> fork of clojure at github 
>>
>> https://github.com/JulesGosnell/clojure
>>
>> Please let me know if you try out the code. I would be interested to hear 
>> if people think it is worth pursuing.
>>
>> I was also thinking that it should be possible to use a similar trick to 
>> quickly and cheaply split a map/set into [roughly] equal sized pieces 
>> (assuming an good hash distribution). This would enable the use of a 
>> map/set as an input sequence into the parallel reduction process outlined 
>> above. Currently, I believe that only a vector can be used in this way. It 
>> would be harder to arrange that 'count' could be implemented efficiently on 
>> these sub-maps/sets, but this is not important for th

Re: ANN: om-sync

2014-02-15 Thread Conrad Barski
On Thursday, February 13, 2014 8:55:00 PM UTC-6, David Nolen wrote:
> I've been banging the drum about Om & modularity for a while now and I've 
> come up with the very beginning of a simple reusable component that I think 
> demonstrates the power of Om's emphasis on modularity and application wide 
> state management:
> 
> 
> 
> http://github.com/swannodette/om-sync
> 
> 
> 
> The whole point of Om is to create a universe of shareable components. I hope 
> this gets people thinking about the possibilities.
> 
> 
> 
> Feedback welcome!
> 
> 
> David

I agree that creating an ecosystem of components is where the future is... I'm 
surprised that there isn't a "ReactjsUI" library yet.

Stop me if this is obvious, but it seems like the natural conclusion of Om is 
to have an Om-server library as well to build html server-side, and then have 
an Om-bridge component or something that automagically bridges between client 
and server. Then, when a client-side component updates any state that 
originates in the server part, the existing Om interfaces probably are already 
comprehensive enough that the Om-bridge component could just transparently use 
AJAX to push those updates into the state of the Om components residing on the 
server.

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


Re: ANN: om-sync

2014-02-15 Thread Mikera


On Sunday, 16 February 2014 09:26:18 UTC+8, Conrad wrote:
>
> On Thursday, February 13, 2014 8:55:00 PM UTC-6, David Nolen wrote: 
> > I've been banging the drum about Om & modularity for a while now and 
> I've come up with the very beginning of a simple reusable component that I 
> think demonstrates the power of Om's emphasis on modularity and application 
> wide state management: 
> > 
> > 
> > 
> > http://github.com/swannodette/om-sync 
> > 
> > 
> > 
> > The whole point of Om is to create a universe of shareable components. I 
> hope this gets people thinking about the possibilities. 
> > 
> > 
> > 
> > Feedback welcome! 
> > 
> > 
> > David 
>
> I agree that creating an ecosystem of components is where the future is... 
> I'm surprised that there isn't a "ReactjsUI" library yet. 
>
> Stop me if this is obvious, but it seems like the natural conclusion of Om 
> is to have an Om-server library as well to build html server-side, and then 
> have an Om-bridge component or something that automagically bridges between 
> client and server. Then, when a client-side component updates any state 
> that originates in the server part, the existing Om interfaces probably are 
> already comprehensive enough that the Om-bridge component could just 
> transparently use AJAX to push those updates into the state of the Om 
> components residing on the server.


It's not clear to me that the server side should be tied to Om 
specifically. It seems like the requirement is more to have a server 
component that can pass messages / state changes in a generic way to 
clients (probably using core.async channels, with the ability to use 
websockets etc. as the underlying transport). This server component would 
be useful for all kinds of clients (not just Om, not just Clojurescript, 
maybe even other server systems).

I've hacked some stuff together that does this kind of thing for specific 
projects, but it would be nice to get a solid standard library in the 
ecosystem for this.

 

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


Re: java.jdbc 0.3.3 select query exception: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

2014-02-15 Thread The Dude (Abides)
Thanks, here's the entire stack trace:

java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to 
clojure.lang.IFn
 members.clj:33 sikhpyar.routes.members/get-member
 members.clj:50 sikhpyar.routes.members/fn
core.clj:94 compojure.core/make-route[fn]
core.clj:40 compojure.core/if-route[fn]
core.clj:25 compojure.core/if-method[fn]
   core.clj:107 compojure.core/routing[fn]
  core.clj:2443 clojure.core/some
   core.clj:107 compojure.core/routing
RestFn.java:139 clojure.lang.RestFn.applyTo
   core.clj:619 clojure.core/apply
   core.clj:112 compojure.core/routes[fn]
   core.clj:107 compojure.core/routing[fn]
  core.clj:2443 clojure.core/some
   core.clj:107 compojure.core/routing
RestFn.java:139 clojure.lang.RestFn.applyTo
   core.clj:619 clojure.core/apply
   core.clj:112 compojure.core/routes[fn]
  middleware.clj:17 
sikhpyar.middleware/template-error-page[fn]
  middleware.clj:10 sikhpyar.middleware/log-request[fn]
  middleware.clj:44 
noir.util.middleware/wrap-request-map[fn]
  keyword_params.clj:32 
ring.middleware.keyword-params/wrap-keyword-params[fn]
   nested_params.clj:70 
ring.middleware.nested-params/wrap-nested-params[fn]
  params.clj:58 ring.middleware.params/wrap-params[fn]
  middleware.clj:12 hiccup.middleware/wrap-base-url[fn]
   multipart_params.clj:107 
ring.middleware.multipart-params/wrap-multipart-params[fn]
 validation.clj:153 noir.validation/wrap-noir-validation[fn]
 cookies.clj:72 noir.cookies/noir-cookies[fn]
cookies.clj:171 ring.middleware.cookies/wrap-cookies[fn]
session.clj:142 noir.session/noir-flash[fn]
   flash.clj:31 ring.middleware.flash/wrap-flash[fn]
 session.clj:97 noir.session/noir-session[fn]
 session.clj:85 ring.middleware.session/wrap-session[fn]
   Var.java:415 clojure.lang.Var.invoke
  reload.clj:18 ring.middleware.reload/wrap-reload[fn]
  stacktrace.clj:17 
ring.middleware.stacktrace/wrap-stacktrace-log[fn]
  stacktrace.clj:80 
ring.middleware.stacktrace/wrap-stacktrace-web[fn]
   jetty.clj:18 ring.adapter.jetty/proxy-handler[fn]
   (Unknown Source) 
ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$0.handle
HandlerWrapper.java:116 
org.eclipse.jetty.server.handler.HandlerWrapper.handle
Server.java:363 org.eclipse.jetty.server.Server.handle
AbstractHttpConnection.java:483 
org.eclipse.jetty.server.AbstractHttpConnection.handleRequest
AbstractHttpConnection.java:920 
org.eclipse.jetty.server.AbstractHttpConnection.headerComplete
AbstractHttpConnection.java:982 
org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete
HttpParser.java:635 
org.eclipse.jetty.http.HttpParser.parseNext
HttpParser.java:235 
org.eclipse.jetty.http.HttpParser.parseAvailable
AsyncHttpConnection.java:82 
org.eclipse.jetty.server.AsyncHttpConnection.handle
 SelectChannelEndPoint.java:628 
org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle
  SelectChannelEndPoint.java:52 
org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run
  QueuedThreadPool.java:608 
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob
  QueuedThreadPool.java:543 
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run
Thread.java:744 java.lang.Thread.run

Here's the route function:

(defn get-a-member [id]
(let [id (parse-int id) member]
[member (memberdb/get-member id)]
(session/put! :member-id (member :id))
(session/put! :nexto (+ (member :id) 1))
(session/put! :username  (member :username))
(session/put! :firstname (member :firstname))
(session/put! :lastname  (member :lastname))
(session/put! :email (member :email))
(layout/render "member/profile2.html" {:member member})))

The route:

(GET "/member/:id" [id] (get-a-member id))

The model:

(defmulti parse-int type)
(defmethod parse-int java.lang.Integer [n] n)
(defmethod parse-int java.lang.String [s] (Integer/parseInt s))

(defn get-member [id]
  (let [id (parse-int id)]
  (jdbc/query  db ["SELECT * FROM members WHERE id = ? LIMIT 1" id])))

I'm using parse-int to explicitly specify id as an integer.

If I use just the query with no output to layout, or sessions, etc, it does 
show the output from the db.

If I put just (str id) on the route handle

Re: java.jdbc 0.3.3 select query exception: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

2014-02-15 Thread edbond
I spot invalid let here:

(defn get-a-member [id]
(let [id (parse-int id) member]
[member (memberdb/get-member id)]

should be 

(defn get-a-member [id]
(let [id (parse-int id)
  member (memberdb/get-member id)]


On Sunday, February 16, 2014 4:01:03 AM UTC+2, The Dude (Abides) wrote:
>
> Thanks, here's the entire stack trace:
>
> java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to 
> clojure.lang.IFn
>  members.clj:33 sikhpyar.routes.members/get-member
>  members.clj:50 sikhpyar.routes.members/fn
> core.clj:94 compojure.core/make-route[fn]
> core.clj:40 compojure.core/if-route[fn]
> core.clj:25 compojure.core/if-method[fn]
>core.clj:107 compojure.core/routing[fn]
>   core.clj:2443 clojure.core/some
>core.clj:107 compojure.core/routing
> RestFn.java:139 clojure.lang.RestFn.applyTo
>core.clj:619 clojure.core/apply
>core.clj:112 compojure.core/routes[fn]
>core.clj:107 compojure.core/routing[fn]
>   core.clj:2443 clojure.core/some
>core.clj:107 compojure.core/routing
> RestFn.java:139 clojure.lang.RestFn.applyTo
>core.clj:619 clojure.core/apply
>core.clj:112 compojure.core/routes[fn]
>   middleware.clj:17 
> sikhpyar.middleware/template-error-page[fn]
>   middleware.clj:10 sikhpyar.middleware/log-request[fn]
>   middleware.clj:44 
> noir.util.middleware/wrap-request-map[fn]
>   keyword_params.clj:32 
> ring.middleware.keyword-params/wrap-keyword-params[fn]
>nested_params.clj:70 
> ring.middleware.nested-params/wrap-nested-params[fn]
>   params.clj:58 ring.middleware.params/wrap-params[fn]
>   middleware.clj:12 hiccup.middleware/wrap-base-url[fn]
>multipart_params.clj:107 
> ring.middleware.multipart-params/wrap-multipart-params[fn]
>  validation.clj:153 
> noir.validation/wrap-noir-validation[fn]
>  cookies.clj:72 noir.cookies/noir-cookies[fn]
> cookies.clj:171 
> ring.middleware.cookies/wrap-cookies[fn]
> session.clj:142 noir.session/noir-flash[fn]
>flash.clj:31 ring.middleware.flash/wrap-flash[fn]
>  session.clj:97 noir.session/noir-session[fn]
>  session.clj:85 
> ring.middleware.session/wrap-session[fn]
>Var.java:415 clojure.lang.Var.invoke
>   reload.clj:18 ring.middleware.reload/wrap-reload[fn]
>   stacktrace.clj:17 
> ring.middleware.stacktrace/wrap-stacktrace-log[fn]
>   stacktrace.clj:80 
> ring.middleware.stacktrace/wrap-stacktrace-web[fn]
>jetty.clj:18 ring.adapter.jetty/proxy-handler[fn]
>(Unknown Source) 
> ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$0.handle
> HandlerWrapper.java:116 
> org.eclipse.jetty.server.handler.HandlerWrapper.handle
> Server.java:363 org.eclipse.jetty.server.Server.handle
> AbstractHttpConnection.java:483 
> org.eclipse.jetty.server.AbstractHttpConnection.handleRequest
> AbstractHttpConnection.java:920 
> org.eclipse.jetty.server.AbstractHttpConnection.headerComplete
> AbstractHttpConnection.java:982 
> org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete
> HttpParser.java:635 
> org.eclipse.jetty.http.HttpParser.parseNext
> HttpParser.java:235 
> org.eclipse.jetty.http.HttpParser.parseAvailable
> AsyncHttpConnection.java:82 
> org.eclipse.jetty.server.AsyncHttpConnection.handle
>  SelectChannelEndPoint.java:628 
> org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle
>   SelectChannelEndPoint.java:52 
> org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run
>   QueuedThreadPool.java:608 
> org.eclipse.jetty.util.thread.QueuedThreadPool.runJob
>   QueuedThreadPool.java:543 
> org.eclipse.jetty.util.thread.QueuedThreadPool$3.run
> Thread.java:744 java.lang.Thread.run
>
> Here's the route function:
>
> (defn get-a-member [id]
> (let [id (parse-int id) member]
> [member (memberdb/get-member id)]
> (session/put! :member-id (member :id))
> (session/put! :nexto (+ (member :id) 1))
> (session/put! :username  (member :username))
> (session/put! :firstname (member :firstname))
> (session/put! :lastname  (member :lastname))
> (session/put! :email (member :email))
> (layout/render "member/profile2.html" {:member member})))
>
> The route:
>
> (GET "/member/:id" [id] (get-a

Re: [ANN] Clojure 1.6.0-beta1

2014-02-15 Thread Эльдар Габдуллин
Like this, just

not-nil?
if-not-nil
when-not-nil

is much better for me.



суббота, 15 февраля 2014 г., 7:12:21 UTC+4 пользователь Joel Holdbrooks 
написал:
>
> As an addendum to my last comment, *not-nil?* would also be a good 
> candidate. That really doesn't leave room for doubt.
>
> This:
>   
> (some? false) ;; => true 
>
> Would confuse me. On the other hand this:
>   
> (not-nil? false) ;; => true 
>
> Would not.
>
> There's really no need to complicate the naming story here. It's also easy 
> to remember!
>
> On Friday, February 14, 2014 3:25:36 PM UTC-8, Alex Miller wrote:
>>
>>
>>
>> On Friday, February 14, 2014 2:27:49 PM UTC-6, DomKM wrote:
>>>
>>> Great changes! I have a question about #5.
>>>  
>>>
 5) New "some" operations 
 Many conditional functions rely on logical truth (where "falsey"
 values are nil or false). Sometimes it is useful to have functions
 that rely on "not nilness" instead. These functions have been added to
 support these cases [CLJ-1343]:
 * some? - same as (not (nil? x))
 * if-some - like if-let, but checks (not (nil? test)) instead of test
 * when-some - like when-let, but checks (not (nil? test)) instead of 
 test
>>>
>>>
>>> It seems inconsistent to have "some" mean two very different things 
>>> within the same namespace, especially since the prior uses of "some" 
>>> (`some`, `some-fn`, etc.) are more in keeping with its primary definition 
>>> of having to do with amount (and operate on seqs or variadic arguments) 
>>> while the new functions have to do with existence (and operate on any 
>>> single value). Why not call these new functions `not-nil?`, `if-not-nil`, 
>>> and `when-not-nil`? Or, if "not-nil" is too unwieldy then what about 
>>> "exists" (`exists?`, `if-exists`, `when-exists`)?
>>>
>>> Are these names up for discussion?
>>>
>>
>> Hey Dom et al,
>>
>> The names of these functions were chosen by Rich. There was already some 
>> name overloading of "some" even before these new functions with some 
>> (truthy) and some->/some->> (not nil). The new functions keep with the 
>> latter meaning. Many other names were considered, including everything I've 
>> seen someone mention (-not-nil, exists, nnil, etc). As far as I know these 
>> names are final, however, I will relay all of the feedback I've seen here, 
>> on #clojure, and on Twitter to Rich for consideration.
>>
>> Alex
>>  
>>
>

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