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

2014-02-16 Thread Jan Herich
Hi t x,

I think, that lock-free approach an it's semantics is more in line with 
other Clojure reference types such as refs.
It also encourages you to only use pure functions for state transitions, 
among other things, such as significant
performance benefits in comparison with lock based approaches, see for 
example this 
article
. 
If you really want to update some reference with function which will also 
perform "impure" actions such as file I/O,
consider using agents  and 
sendor
 
send-off(the
 latter in case of I/O blocking actions), functions given to send 
and send-off are guaranteed to run only once.

Dňa pondelok, 17. februára 2014 2:36:59 UTC+1 t x napísal(-a):
>
> Hi Jan, 
>
>   You're right. I'm wrong. 
>
>   I'm grateful you pointed this out -- this would have otherwise been 
> impossible to debug. 
>
> === 
>
> To everyone: 
>
>   Why can swap! be retried? This confuses me -- to implement swap!, why 
> can't we 
>
>   * have a lock 
>
>   * ensure that only one swap! is in session at any given time 
>
>   * have the given swap! complete before running the next swap! 
>
>
> Thanks! 
>
>
> On Sun, Feb 16, 2014 at 3:51 PM, Jan Herich > 
> wrote: 
> > I'm afraid your understanding of atom swap! operations is not quite 
> correct 
> > -> update function must (or should) be pure as well. 
> > See the documentation for swap!, update function could be potentially 
> called 
> > multiple times if there are more threads of execution 
> > updating one atomic reference -> there is simple compare and set 
> mechanism 
> > involved, which compares the old value of the atom 
> > (input for the update function) and sets the atom to new value (return 
> value 
> > from the update function) only value of the atom reference 
> > was not changed in between, if yes the compare and set is retried until 
> ti 
> > succeeds. 
> > 
> > Dňa nedeľa, 16. februára 2014 23:35:24 UTC+1 t x napísal(-a): 
> >> 
> >> I believe that's the STM approach, which has the advanrtage of: 
> >> 
> >>   * can synchronize across multiple pieces of data 
> >> 
> >> but has the disadvantage of: 
> >> 
> >>   * work must be "pure" since it can be retried 
> >> 
> >>   * possibly less efficient due to possibility of retrying 
> >> 
> >> 
> >> In the example I posted above, I only need to: 
> >> 
> >>   * modify a single atom 
> >> 
> >> and the approach I presented above: 
> >> 
> >>   * can be impure, since it is guaranteed to only run once 
> >> 
> >>   * is guaranteed to succeed (without retrys) 
> >> 
> >> On Sun, Feb 16, 2014 at 2:25 PM, Ramesh  wrote: 
> >> > You can use a ref instead of an atom. And use dosync with multiple 
> >> > alter, so 
> >> > everything is safely inside a transaction. 
> >> > 
> >> > On Feb 16, 2014 2:04 PM, "t x"  wrote: 
> >> >> 
> >> >> Hi John, 
> >> >> 
> >> >>   Your solution is perfectly valid and optimal for the problem I 
> >> >> described above. 
> >> >> 
> >> >> 
> >> >>   Unfortunately, I forgot to mention an additional constraint: 
> >> >> sometimes I 
> >> >> do: 
> >> >> 
> >> >> (let [ foo (:some-selector @data-atom) ] 
> >> >>   (swap! data-atom update-in [:other-selector] ... )) 
> >> >> 
> >> >> which the -> doesn't quite work on, but my ugly hack above does 
> >> >> resolve. 
> >> >> 
> >> >> 
> >> >>   The problem being -- I want to update one part of the atom, but it 
> >> >> depends on another part of the atom. 
> >> >> 
> >> >>   I ended up with the following hack: 
> >> >> 
> >> >> (defn tswap! [atm func] 
> >> >>   (swap! atm 
> >> >>  (fn [old] 
> >> >>(let [natm (atom old)] 
> >> >>  (func natm) 
> >> >>  @natm 
> >> >> 
> >> >> 
> >> >> On Sat, Feb 15, 2014 at 4:09 PM, John D. Hume  
>
> >> >> wrote: 
> >> >> > 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 clo...@googlegroups.com 
> >> >> > Note that posts from new members are moderated - please be patient 
> >> >> > with 
> >> >> > your 
> >> >> > first post. 
> >> >> > To unsubscribe from this group, send email to 
> >> >> > clojure+u...@googlegroups.com 
> >> >> > For more options,

Re: Looking for advice to fine tune a simple function

2014-02-16 Thread Bruno Kim Medeiros Cesar
I can't claim to be an experienced Clojure developer, specially so 
regarding maintainability as I'm the only reader of what I write. Andy 
provided a great piece of code, although I scratched my head for a second 
or two unwrapping the last two lines. You'll be surprised how often 
(partition * 1) comes up, as it provides a sliding window through a 
sequence.

(BTW, Andy, how do you format your code so prettily?)

Regarding your question about expecting a sorted input: why don't you 
ensure it? These are the (very similar) options to enforce a precondition 
that I know of:










*(defn hr-zone [bpm [zone-1 zone-2 zone-3 zone-4 :as zones]]  {:pre [(< 
zone-1 zone-2 zone-3 zone-4)]} ...) ; I don't see this very often, but it's 
simple(defn hr-zone [bpm [zone-1 zone-2 zone-3 zone-4 :as zones]]  (assert 
(< zone-1 zone-2 zone-3 zone-4)} "Not sorted!") ...) ; throws an error just 
as the above one, but with a provided message(defn hr-zone [bpm [zone-1 
zone-2 zone-3 zone-4 :as zones]]  (when-not (< zone-1 zone-2 zone-3 
zone-4)} (throw (Exception. "Not sorted!"))) ...) ; If you want to be able 
to catch the error, you may throw an exception*sorted? does not do what you 
may expect: it tests whether the data structure implements Sorted, such as 
sorted-set and sorted-map. You may get the same behaviour with (apply <= 
coll) or (apply < coll) for numeric collections.

For me, the simplest option is




*(defn hr-zone [bpm zones]  (let [[zone-1 zone-2 zone-3 zone-4] (sort 
zones)]...)*
which never fails, although may not be what you need (for example, you'd 
like to be alerted if you input [174 178 128 186] when you wanted [174 178 
182 186]).

Hope that helps a bit,

Bruno Kim.

On Sunday, February 16, 2014 7:31:46 PM UTC-3, Laurent Droin wrote:
>
> Hi,
>
> Disclaimer - I am completely new to Clojure. I just implemented my very 
> first (simple) program, letting me find out, from a GPX file, how much time 
> is spent in the various heart rate zones. Now that it's working, I'm 
> reviewing the code and trying to use best practices. From what I have read 
> so far, there are many ways in Clojure to do the same thing and for a 
> newbie, it's not always obvious to get a good grasp on what is the best way 
> to  code a feature.
> As a developer, and even though I love how concise Clojure programs can 
> be, I am very concerned with readability and ease of maintenance so I would 
> like to keep functions as short and tight as possible, but not to the point 
> where it becomes hard to understand what it does.
>
> Here is a function that I came up with that takes  a bpm (heart beats per 
> minute) value, as well as a sequence of 4 values that represent the 
> boundaries defining the 5 different heart rate zones for a particular 
> person.
> The function needs to finds out in what heart zone the bpm value falls 
> into and return that zone (as a keyword - I later use that keyword in a 
> map).
>
> If you're an experienced Clojure developer, what would you have done 
> differently (and why) ?
>
> *(defn hr-zone*
> *  "Return the HR zone as a keyword according to the bpm value."*
> *  [bpm [max-zone-1 max-zone-2 max-zone-3 max-zone-4]] *
> *  (cond *
> *(<= bpm max-zone-1) :hr-zone-1*
> *(and (< max-zone-1 bpm) (>= max-zone-2 bpm)) :hr-zone-2 *
> *(and (< max-zone-2 bpm) (>= max-zone-3 bpm)) :hr-zone-3 *
> *(and (< max-zone-3 bpm) (>= max-zone-4 bpm)) :hr-zone-4 *
> *(< max-zone-4 bpm) :hr-zone-5))*
>
> FYI, here is how I call this function in the REPL:
> (def my-hr-zones-defs [120 150 165 180])
>
> (hr-zone 115 my-hr-zones-defs)
> (hr-zone 133 my-hr-zones-defs)
> (hr-zone 161 my-hr-zones-defs)
> (hr-zone 175 my-hr-zones-defs)
> (hr-zone 192 my-hr-zones-refs)
>
> Questions I have:
> Would that make sense to consider (and maybe enforce) that the sequence 
> received as parameter is sorted? If this was the case, I would assume I 
> could avoid the "and" calls- assuming that all the conditions in the cone 
> form are evaluated in order. 
> Assuming that I need to test bpm against the two boundaries of each range, 
> would there be a better way to do this:
> *(and (< max-zone-1 bpm) (>= max-zone-2 bpm))*
> ?
> Maybe this would work, but is it preferable?
> *(< max-zone-1 bpm (dec **max-zone-2**))*
>
> *Thanks in advance for the advice.*
>
> *Laurent. *
>
>

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

Re: Some advice about introducing clojurescript into a project using js/jquery

2014-02-16 Thread Kashyap CK
Thank you Dave and David,

Regards,
Kashyap

On Monday, February 17, 2014 8:26:25 AM UTC+5:30, David Della Costa wrote:
>
> Just because you are using jQuery extensively in your JS codebase 
> doesn't mean you need jayq/jQuery in your ClojureScript code.  If you 
> are trying to do inter-op and call some of your JavaScript code from 
> your ClojureScript code, then you can simply use standard JavaScript 
> inter-op; if you want to user your ClojureScript functions in JS you 
> simply need to label those functions with the metadata ^:export and call 
> them in a namespace-qualified fashion. 
>
> externs are only necessary when you need to tell the Google Closure 
> compiler that it should not mangle certain names when compiling in 
> advanced mode 
> (https://developers.google.com/closure/compiler/docs/api-tutorial3). 
> That being the case, you only really need to make sure you have an 
> externs file which includes JS function names that you are referring to 
> in your ClojureScript code, and that is only if you are compiling in 
> advanced mode.  If you use jayq in advanced mode, of course you'll need 
> this (https://github.com/ibdknox/jayq#compiling), but if you don't 
> include it you don't need to think about it...or jQuery. 
>
> If you find you need to access the DOM in your ClojureScript code I 
> would suggest starting with something like dommy or even the default 
> Google closure libraries (the approach David Nolen takes in most of his 
> blog posts). 
>
> DD 
>
>
> (2014/02/16 23:47), Kashyap CK wrote: 
> > Hi, 
> > 
> > It took me some time to get started with clojurescript (on 
> > windows/cygwin) 
> > - http://swannodette.github.io/2013/11/07/clojurescript-101/ worked for 
> me. 
> > 
> > I'd like to use clojurescript to do some UI component development for 
> > product which is built using webkit/js/jquery. I was wondering if it is 
> > okay to develop a feature in such an application, where most of the UI 
> > is in jquery, in clojurescript? 
> > 
> > I'd appreciate it very much to know if there are any known gotha's here 
> > or any tips that I could use?   
> > 
> > Regards, 
> > Kashyap 
> > 
> > -- 
> > You received this message because you are subscribed to the Google 
> > Groups "Clojure" group. 
> > To post to this group, send email to clo...@googlegroups.com 
> > Note that posts from new members are moderated - please be patient with 
> > your first post. 
> > To unsubscribe from this group, send email to 
> > clojure+u...@googlegroups.com  
> > For more options, visit this group at 
> > http://groups.google.com/group/clojure?hl=en 
> > --- 
> > You received this message because you are subscribed to the Google 
> > Groups "Clojure" group. 
> > To unsubscribe from this group and stop receiving emails from it, send 
> > an email to clojure+u...@googlegroups.com . 
> > For more options, visit https://groups.google.com/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: Latex style file for formatting/coloring clojure code?

2014-02-16 Thread Andy-
On Sunday, February 16, 2014 6:05:24 PM UTC-5, puzzler wrote:
>
> I am unable to find a style file that supports clojure code in LaTeX.  Can 
> anyone point me in the right direction?
>
Pygments can output LaTeX. (There is also minted)

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: Some advice about introducing clojurescript into a project using js/jquery

2014-02-16 Thread Dave Della Costa
Just because you are using jQuery extensively in your JS codebase
doesn't mean you need jayq/jQuery in your ClojureScript code.  If you
are trying to do inter-op and call some of your JavaScript code from
your ClojureScript code, then you can simply use standard JavaScript
inter-op; if you want to user your ClojureScript functions in JS you
simply need to label those functions with the metadata ^:export and call
them in a namespace-qualified fashion.

externs are only necessary when you need to tell the Google Closure
compiler that it should not mangle certain names when compiling in
advanced mode
(https://developers.google.com/closure/compiler/docs/api-tutorial3).
That being the case, you only really need to make sure you have an
externs file which includes JS function names that you are referring to
in your ClojureScript code, and that is only if you are compiling in
advanced mode.  If you use jayq in advanced mode, of course you'll need
this (https://github.com/ibdknox/jayq#compiling), but if you don't
include it you don't need to think about it...or jQuery.

If you find you need to access the DOM in your ClojureScript code I
would suggest starting with something like dommy or even the default
Google closure libraries (the approach David Nolen takes in most of his
blog posts).

DD


(2014/02/16 23:47), Kashyap CK wrote:
> Hi,
> 
> It took me some time to get started with clojurescript (on
> windows/cygwin)
> - http://swannodette.github.io/2013/11/07/clojurescript-101/ worked for me.
> 
> I'd like to use clojurescript to do some UI component development for
> product which is built using webkit/js/jquery. I was wondering if it is
> okay to develop a feature in such an application, where most of the UI
> is in jquery, in clojurescript?
> 
> I'd appreciate it very much to know if there are any known gotha's here
> or any tips that I could use?  
> 
> Regards,
> Kashyap
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To unsubscribe from 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.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from 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-16 Thread Mars0i
I like Alex's suggestions.  Another option is "something" rather than 
"some" or "exists".  "Something" has the disadvantage that it's long, so 
when you combine it with addition strings, you get something even longer.  

On the other hand, for me both "some" and "exists" sound like existential 
quantifiers in logic, as in "Some x is F",  "There exists an x such that 
Fx".  The clojure function *every?* plays the role of the universal 
quantifier (All x are F), and the *some* function plays the role of the 
existential quantifier, although it does more.

However, a function named "something?" doesn't really sound like an 
existential quantifier (despite the fact that in English "something" can be 
used to express the existential quantifier ("something is F").  Rather, 
"something?" suggests that there's something, rather than nothing, i.e. 
rather than nil.

(something? false) => false
is still a little bit confusing, but if you think of it as saying that 
falsehood is not nothing, then maybe it makes sense.


On Sunday, February 16, 2014 11:29:38 AM UTC-6, Alex Walker wrote:
>
> Part of Rich's objection to not-nil? variants could be that they are a 
> double negative, "not-(no value)?", which can decrease clarity and require 
> more coffee.
>
>
>>- nil Means 'nothing/no-value'- represents Java null and tests 
>>logical false [clojure.org/reader]
>>
>>
> To compete with some? variants, I'd suggest a positive that I found 
> strangely available:
>
> exists?
> if-exists[?]
> when-exists[?]
>
> Or, more proper, though potentially more overloaded: value?, if-value[?], 
> when-value[?].
>
> On Sunday, February 16, 2014 12:54:12 AM UTC-6, Эльдар Габдуллин wrote:
>>
>> 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.


Re: Looking for advice to fine tune a simple function

2014-02-16 Thread Andy-
I realized I could use that at some of my code so I wrote it. Not sure if 
it's the best possible implementation but here it is:

(defn quantizer
  "Returns a function that quantizes input data which when called with 'x' 
returns:   o <1st val> if-Inf < x <= <1st bound>   o <2st val> if <1st 
bound> < x <= <2st bound>   o ...   o  if  < x <=o >max if x >  where m is a vector of vectors where 
the first element specifies the boundary and   the second element the value 
which to return. Example:   (def points->grade (quantizer [[40 :F] [60 :D] 
[80 :C] [90 :B]] :A))   (map points->grade [10 80 93])   ; (:F :C :A)"
  [m >max]
  (fn [x]
(if (<= x (first (first m)))
  (second (first m))
  (if (> x (first (last m)))
>max
(some 
 (fn [i] 
   (let [[[l lv] [h hv]] i]
 (and (< l x) (<= x h) hv)))
 (partition 2 1 m))


Cheers


On Sunday, February 16, 2014 6:47:51 PM UTC-5, Andy- wrote:
>
> I'm also very new to clojure but this is how I'd do it:
>
> (def hr-zones {
>[0 100] :low
>[101 120] :fat-burn
>[121 140] :aerobic
>[141 160] :anaerobic
>[161 333] :max})
>
> (defn hr->zone [hr]
>   (some (fn [x]
> (and (<= (first (key x)) hr (second (key x)))
>  (val x)))
> hr-zones))
>
>
> This method does have some disadvantages however (you have to make sure 
> the boundaries are correct and it doesn't handle floating points like 
> 140.4).
>
> Whenever you see yourself repeating code (like the 3-4 if's you have) then 
> you have to take a step back and maybe change your data structure so that 
> your algorithm is easier.
>
> Mathematically speaking you're really quantizing your data (aka applying a 
> piecewise constant function). So you could even take another step back and 
> make it more general. So find a data structure that represents the function 
> (ie the intervals and the function value for each interval) and then you 
> could come up with a function like "quantize" or "mk-piecewise-const-fn" 
> that returns a function. So you could then do:
>
> (let [myfn (mk-piecewise-const-fn [[100 :zone-1] [120 :zone-2] ...] ]
>myzone (myfn 142)]
>
> and you have a general function  which you can now use with a much wider 
> range of problems (not just specific to your hr->zone conversion).
>
> But I'm too lazy to come up with a implementation for 
> mk-piecewise-const-fn :)
>
> HTH
>
>
> On Sunday, February 16, 2014 5:31:46 PM UTC-5, Laurent Droin wrote:
>>
>> Hi,
>>
>> Disclaimer - I am completely new to Clojure. I just implemented my very 
>> first (simple) program, letting me find out, from a GPX file, how much time 
>> is spent in the various heart rate zones. Now that it's working, I'm 
>> reviewing the code and trying to use best practices. From what I have read 
>> so far, there are many ways in Clojure to do the same thing and for a 
>> newbie, it's not always obvious to get a good grasp on what is the best way 
>> to  code a feature.
>> As a developer, and even though I love how concise Clojure programs can 
>> be, I am very concerned with readability and ease of maintenance so I would 
>> like to keep functions as short and tight as possible, but not to the point 
>> where it becomes hard to understand what it does.
>>
>> Here is a function that I came up with that takes  a bpm (heart beats per 
>> minute) value, as well as a sequence of 4 values that represent the 
>> boundaries defining the 5 different heart rate zones for a particular 
>> person.
>> The function needs to finds out in what heart zone the bpm value falls 
>> into and return that zone (as a keyword - I later use that keyword in a 
>> map).
>>
>> If you're an experienced Clojure developer, what would you have done 
>> differently (and why) ?
>>
>> *(defn hr-zone*
>> *  "Return the HR zone as a keyword according to the bpm value."*
>> *  [bpm [max-zone-1 max-zone-2 max-zone-3 max-zone-4]] *
>> *  (cond *
>> *(<= bpm max-zone-1) :hr-zone-1*
>> *(and (< max-zone-1 bpm) (>= max-zone-2 bpm)) :hr-zone-2 *
>> *(and (< max-zone-2 bpm) (>= max-zone-3 bpm)) :hr-zone-3 *
>> *(and (< max-zone-3 bpm) (>= max-zone-4 bpm)) :hr-zone-4 *
>> *(< max-zone-4 bpm) :hr-zone-5))*
>>
>> FYI, here is how I call this function in the REPL:
>> (def my-hr-zones-defs [120 150 165 180])
>>
>> (hr-zone 115 my-hr-zones-defs)
>> (hr-zone 133 my-hr-zones-defs)
>> (hr-zone 161 my-hr-zones-defs)
>> (hr-zone 175 my-hr-zones-defs)
>> (hr-zone 192 my-hr-zones-refs)
>>
>> Questions I have:
>> Would that make sense to consider (and maybe enforce) that the sequence 
>> received as parameter is sorted? If this was the case, I would assume I 
>> could avoid the "and" calls- assuming that all the conditions in the cone 
>> form are evaluated in order. 
>> Assuming that I need to test bpm against the two boundaries of each 
>> range, would there be a better way to do this:
>> *(and (< max-zone-1 bpm) (>= max-zone-2 bpm))*
>> ?
>> Maybe this would wo

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

2014-02-16 Thread t x
Hi Jan,

  You're right. I'm wrong.

  I'm grateful you pointed this out -- this would have otherwise been
impossible to debug.

===

To everyone:

  Why can swap! be retried? This confuses me -- to implement swap!, why can't we

  * have a lock

  * ensure that only one swap! is in session at any given time

  * have the given swap! complete before running the next swap!


Thanks!


On Sun, Feb 16, 2014 at 3:51 PM, Jan Herich  wrote:
> I'm afraid your understanding of atom swap! operations is not quite correct
> -> update function must (or should) be pure as well.
> See the documentation for swap!, update function could be potentially called
> multiple times if there are more threads of execution
> updating one atomic reference -> there is simple compare and set mechanism
> involved, which compares the old value of the atom
> (input for the update function) and sets the atom to new value (return value
> from the update function) only value of the atom reference
> was not changed in between, if yes the compare and set is retried until ti
> succeeds.
>
> Dňa nedeľa, 16. februára 2014 23:35:24 UTC+1 t x napísal(-a):
>>
>> I believe that's the STM approach, which has the advanrtage of:
>>
>>   * can synchronize across multiple pieces of data
>>
>> but has the disadvantage of:
>>
>>   * work must be "pure" since it can be retried
>>
>>   * possibly less efficient due to possibility of retrying
>>
>>
>> In the example I posted above, I only need to:
>>
>>   * modify a single atom
>>
>> and the approach I presented above:
>>
>>   * can be impure, since it is guaranteed to only run once
>>
>>   * is guaranteed to succeed (without retrys)
>>
>> On Sun, Feb 16, 2014 at 2:25 PM, Ramesh  wrote:
>> > You can use a ref instead of an atom. And use dosync with multiple
>> > alter, so
>> > everything is safely inside a transaction.
>> >
>> > On Feb 16, 2014 2:04 PM, "t x"  wrote:
>> >>
>> >> Hi John,
>> >>
>> >>   Your solution is perfectly valid and optimal for the problem I
>> >> described above.
>> >>
>> >>
>> >>   Unfortunately, I forgot to mention an additional constraint:
>> >> sometimes I
>> >> do:
>> >>
>> >> (let [ foo (:some-selector @data-atom) ]
>> >>   (swap! data-atom update-in [:other-selector] ... ))
>> >>
>> >> which the -> doesn't quite work on, but my ugly hack above does
>> >> resolve.
>> >>
>> >>
>> >>   The problem being -- I want to update one part of the atom, but it
>> >> depends on another part of the atom.
>> >>
>> >>   I ended up with the following hack:
>> >>
>> >> (defn tswap! [atm func]
>> >>   (swap! atm
>> >>  (fn [old]
>> >>(let [natm (atom old)]
>> >>  (func natm)
>> >>  @natm
>> >>
>> >>
>> >> On Sat, Feb 15, 2014 at 4:09 PM, John D. Hume 
>> >> wrote:
>> >> > 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 clo...@googlegroups.com
>> >> > Note that posts from new members are moderated - please be patient
>> >> > with
>> >> > your
>> >> > first post.
>> >> > To unsubscribe from this group, send email to
>> >> > clojure+u...@googlegroups.com
>> >> > For more options, visit this group at
>> >> > http://groups.google.com/group/clojure?hl=en
>> >> > ---
>> >> > You received this message because you are subscribed to the Google
>> >> > Groups
>> >> > "Clojure" group.
>> >> > To unsubscribe from this group and stop receiving emails from it,
>> >> > send
>> >> > an
>> >> > email to clojure+u...@googlegroups.com.
>> >> > For more options, visit https://groups.google.com/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 clo...@googlegroups.com
>> >> Note that posts from new members are moderated - please be patient with
>> >> your first post.
>> >> To unsubscribe from this group, send email to
>> >> clojure+u...@googlegroups.com
>> >> For more options, visit this group at
>> >> http://groups.google.com/group/clojure?hl=en
>> >> ---
>> >> You received this message because you are subscribed to the Google
>> >> Groups
>> >> "Clojure" group.
>> >> To unsubscribe from this group and stop receiving emails from it, send
>> >> an
>> >> email to clojure+u...@googlegroups.com.
>> >> For more options, visit https://groups.google.com/groups/opt_out.
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> > Groups "Clojure" gr

Re: Some advice about introducing clojurescript into a project using js/jquery

2014-02-16 Thread Dave Sann
It works pretty seamlessly.

You will need to include a jquery externs file to avoid munging of function 
call names by the google closure compiler in advanced mode.

See also

https://github.com/ibdknox/jayq

Which adds a few simplifications to usage (particularly some protocols for 
jQuery objects acting as sequences).
There may be others out there too.

if you plan to create elements on the client, you may want to use a "hiccup 
style render", they are very effective and hiccup data is very amenable to 
composition. I use https://github.com/prismatic/dommy. but there are others 
too.

Dave



On Monday, 17 February 2014 01:47:18 UTC+11, Kashyap CK wrote:
>
> Hi,
>
> It took me some time to get started with clojurescript (on windows/cygwin) 
> - http://swannodette.github.io/2013/11/07/clojurescript-101/ worked for 
> me.
>
> I'd like to use clojurescript to do some UI component development for 
> product which is built using webkit/js/jquery. I was wondering if it is 
> okay to develop a feature in such an application, where most of the UI is 
> in jquery, in clojurescript?
>
> I'd appreciate it very much to know if there are any known gotha's here or 
> any tips that I could use?  
>
> Regards,
> Kashyap
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from 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-16 Thread Jan Herich
I'm afraid your understanding of atom swap! operations is not quite correct 
-> update function must (or should) be pure as well.
See the 
documentationfor swap!, 
update function could be potentially called multiple times if 
there are more threads of execution
updating one atomic reference -> there is simple compare and 
setmechanism 
involved, which compares the old value of the atom
(input for the update function) and sets the atom to new value (return 
value from the update function) only value of the atom reference
was not changed in between, if yes the compare and set is retried until ti 
succeeds.

Dňa nedeľa, 16. februára 2014 23:35:24 UTC+1 t x napísal(-a):
>
> I believe that's the STM approach, which has the advanrtage of: 
>
>   * can synchronize across multiple pieces of data 
>
> but has the disadvantage of: 
>
>   * work must be "pure" since it can be retried 
>
>   * possibly less efficient due to possibility of retrying 
>
>
> In the example I posted above, I only need to: 
>
>   * modify a single atom 
>
> and the approach I presented above: 
>
>   * can be impure, since it is guaranteed to only run once 
>
>   * is guaranteed to succeed (without retrys) 
>
> On Sun, Feb 16, 2014 at 2:25 PM, Ramesh > 
> wrote: 
> > You can use a ref instead of an atom. And use dosync with multiple 
> alter, so 
> > everything is safely inside a transaction. 
> > 
> > On Feb 16, 2014 2:04 PM, "t x" > wrote: 
> >> 
> >> Hi John, 
> >> 
> >>   Your solution is perfectly valid and optimal for the problem I 
> >> described above. 
> >> 
> >> 
> >>   Unfortunately, I forgot to mention an additional constraint: 
> sometimes I 
> >> do: 
> >> 
> >> (let [ foo (:some-selector @data-atom) ] 
> >>   (swap! data-atom update-in [:other-selector] ... )) 
> >> 
> >> which the -> doesn't quite work on, but my ugly hack above does 
> resolve. 
> >> 
> >> 
> >>   The problem being -- I want to update one part of the atom, but it 
> >> depends on another part of the atom. 
> >> 
> >>   I ended up with the following hack: 
> >> 
> >> (defn tswap! [atm func] 
> >>   (swap! atm 
> >>  (fn [old] 
> >>(let [natm (atom old)] 
> >>  (func natm) 
> >>  @natm 
> >> 
> >> 
> >> On Sat, Feb 15, 2014 at 4:09 PM, John D. Hume 
> >> > 
>
> >> wrote: 
> >> > 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 
> >> > clo...@googlegroups.com 
> >> > Note that posts from new members are moderated - please be patient 
> with 
> >> > your 
> >> > first post. 
> >> > To unsubscribe from this group, send email to 
> >> > clojure+u...@googlegroups.com  
> >> > For more options, visit this group at 
> >> > http://groups.google.com/group/clojure?hl=en 
> >> > --- 
> >> > You received this message because you are subscribed to the Google 
> >> > Groups 
> >> > "Clojure" group. 
> >> > To unsubscribe from this group and stop receiving emails from it, 
> send 
> >> > an 
> >> > email to clojure+u...@googlegroups.com . 
> >> > For more options, visit https://groups.google.com/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 clo...@googlegroups.com 
> >> Note that posts from new members are moderated - please be patient with 
> >> your first post. 
> >> To unsubscribe from this group, send email to 
> >> clojure+u...@googlegroups.com  
> >> For more options, visit this group at 
> >> http://groups.google.com/group/clojure?hl=en 
> >> --- 
> >> You received this message because you are subscribed to the Google 
> Groups 
> >> "Clojure" group. 
> >> To unsubscribe from this group and stop receiving emails from it, send 
> an 
> >> email to clojure+u...@googlegroups.com . 
> >> For more options, visit https://groups.google.com/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 clo...@googlegroups.com 
> > Note that posts from new members are moderated - please be patient with 
> your 
> > first post. 
> > To unsubscribe from this group, send email to 
> > clojure+u...@googlegroups.com  
> > For more options, visit this group at 
> > http://groups.google.com/group/clojure?hl=en 
> > --- 
>

Re: Looking for advice to fine tune a simple function

2014-02-16 Thread Andy-
I'm also very new to clojure but this is how I'd do it:

(def hr-zones {
   [0 100] :low
   [101 120] :fat-burn
   [121 140] :aerobic
   [141 160] :anaerobic
   [161 333] :max})

(defn hr->zone [hr]
  (some (fn [x]
(and (<= (first (key x)) hr (second (key x)))
 (val x)))
hr-zones))


This method does have some disadvantages however (you have to make sure the 
boundaries are correct and it doesn't handle floating points like 140.4).

Whenever you see yourself repeating code (like the 3-4 if's you have) then 
you have to take a step back and maybe change your data structure so that 
your algorithm is easier.

Mathematically speaking you're really quantizing your data (aka applying a 
piecewise constant function). So you could even take another step back and 
make it more general. So find a data structure that represents the function 
(ie the intervals and the function value for each interval) and then you 
could come up with a function like "quantize" or "mk-piecewise-const-fn" 
that returns a function. So you could then do:

(let [myfn (mk-piecewise-const-fn [[100 :zone-1] [120 :zone-2] ...] ]
   myzone (myfn 142)]

and you have a general function  which you can now use with a much wider 
range of problems (not just specific to your hr->zone conversion).

But I'm too lazy to come up with a implementation for mk-piecewise-const-fn 
:)

HTH


On Sunday, February 16, 2014 5:31:46 PM UTC-5, Laurent Droin wrote:
>
> Hi,
>
> Disclaimer - I am completely new to Clojure. I just implemented my very 
> first (simple) program, letting me find out, from a GPX file, how much time 
> is spent in the various heart rate zones. Now that it's working, I'm 
> reviewing the code and trying to use best practices. From what I have read 
> so far, there are many ways in Clojure to do the same thing and for a 
> newbie, it's not always obvious to get a good grasp on what is the best way 
> to  code a feature.
> As a developer, and even though I love how concise Clojure programs can 
> be, I am very concerned with readability and ease of maintenance so I would 
> like to keep functions as short and tight as possible, but not to the point 
> where it becomes hard to understand what it does.
>
> Here is a function that I came up with that takes  a bpm (heart beats per 
> minute) value, as well as a sequence of 4 values that represent the 
> boundaries defining the 5 different heart rate zones for a particular 
> person.
> The function needs to finds out in what heart zone the bpm value falls 
> into and return that zone (as a keyword - I later use that keyword in a 
> map).
>
> If you're an experienced Clojure developer, what would you have done 
> differently (and why) ?
>
> *(defn hr-zone*
> *  "Return the HR zone as a keyword according to the bpm value."*
> *  [bpm [max-zone-1 max-zone-2 max-zone-3 max-zone-4]] *
> *  (cond *
> *(<= bpm max-zone-1) :hr-zone-1*
> *(and (< max-zone-1 bpm) (>= max-zone-2 bpm)) :hr-zone-2 *
> *(and (< max-zone-2 bpm) (>= max-zone-3 bpm)) :hr-zone-3 *
> *(and (< max-zone-3 bpm) (>= max-zone-4 bpm)) :hr-zone-4 *
> *(< max-zone-4 bpm) :hr-zone-5))*
>
> FYI, here is how I call this function in the REPL:
> (def my-hr-zones-defs [120 150 165 180])
>
> (hr-zone 115 my-hr-zones-defs)
> (hr-zone 133 my-hr-zones-defs)
> (hr-zone 161 my-hr-zones-defs)
> (hr-zone 175 my-hr-zones-defs)
> (hr-zone 192 my-hr-zones-refs)
>
> Questions I have:
> Would that make sense to consider (and maybe enforce) that the sequence 
> received as parameter is sorted? If this was the case, I would assume I 
> could avoid the "and" calls- assuming that all the conditions in the cone 
> form are evaluated in order. 
> Assuming that I need to test bpm against the two boundaries of each range, 
> would there be a better way to do this:
> *(and (< max-zone-1 bpm) (>= max-zone-2 bpm))*
> ?
> Maybe this would work, but is it preferable?
> *(< max-zone-1 bpm (dec **max-zone-2**))*
>
> *Thanks in advance for the advice.*
>
> *Laurent. *
>
>

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

2014-02-16 Thread gianluca torta
to me it seems that you are anyway relying on the assumption that the 
sequence is ordered, so I think it would be convenient to drop the "and"s

Gianluca


On Sunday, February 16, 2014 11:31:46 PM UTC+1, Laurent Droin wrote:
>
> Hi,
>
> Disclaimer - I am completely new to Clojure. I just implemented my very 
> first (simple) program, letting me find out, from a GPX file, how much time 
> is spent in the various heart rate zones. Now that it's working, I'm 
> reviewing the code and trying to use best practices. From what I have read 
> so far, there are many ways in Clojure to do the same thing and for a 
> newbie, it's not always obvious to get a good grasp on what is the best way 
> to  code a feature.
> As a developer, and even though I love how concise Clojure programs can 
> be, I am very concerned with readability and ease of maintenance so I would 
> like to keep functions as short and tight as possible, but not to the point 
> where it becomes hard to understand what it does.
>
> Here is a function that I came up with that takes  a bpm (heart beats per 
> minute) value, as well as a sequence of 4 values that represent the 
> boundaries defining the 5 different heart rate zones for a particular 
> person.
> The function needs to finds out in what heart zone the bpm value falls 
> into and return that zone (as a keyword - I later use that keyword in a 
> map).
>
> If you're an experienced Clojure developer, what would you have done 
> differently (and why) ?
>
> *(defn hr-zone*
> *  "Return the HR zone as a keyword according to the bpm value."*
> *  [bpm [max-zone-1 max-zone-2 max-zone-3 max-zone-4]] *
> *  (cond *
> *(<= bpm max-zone-1) :hr-zone-1*
> *(and (< max-zone-1 bpm) (>= max-zone-2 bpm)) :hr-zone-2 *
> *(and (< max-zone-2 bpm) (>= max-zone-3 bpm)) :hr-zone-3 *
> *(and (< max-zone-3 bpm) (>= max-zone-4 bpm)) :hr-zone-4 *
> *(< max-zone-4 bpm) :hr-zone-5))*
>
> FYI, here is how I call this function in the REPL:
> (def my-hr-zones-defs [120 150 165 180])
>
> (hr-zone 115 my-hr-zones-defs)
> (hr-zone 133 my-hr-zones-defs)
> (hr-zone 161 my-hr-zones-defs)
> (hr-zone 175 my-hr-zones-defs)
> (hr-zone 192 my-hr-zones-refs)
>
> Questions I have:
> Would that make sense to consider (and maybe enforce) that the sequence 
> received as parameter is sorted? If this was the case, I would assume I 
> could avoid the "and" calls- assuming that all the conditions in the cone 
> form are evaluated in order. 
> Assuming that I need to test bpm against the two boundaries of each range, 
> would there be a better way to do this:
> *(and (< max-zone-1 bpm) (>= max-zone-2 bpm))*
> ?
> Maybe this would work, but is it preferable?
> *(< max-zone-1 bpm (dec **max-zone-2**))*
>
> *Thanks in advance for the advice.*
>
> *Laurent. *
>
>

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


Latex style file for formatting/coloring clojure code?

2014-02-16 Thread Mark Engelberg
I am unable to find a style file that supports clojure code in LaTeX.  Can
anyone point me in the right direction?

Thanks,

Mark

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


Looking for advice to fine tune a simple function

2014-02-16 Thread Laurent Droin
Hi,

Disclaimer - I am completely new to Clojure. I just implemented my very 
first (simple) program, letting me find out, from a GPX file, how much time 
is spent in the various heart rate zones. Now that it's working, I'm 
reviewing the code and trying to use best practices. From what I have read 
so far, there are many ways in Clojure to do the same thing and for a 
newbie, it's not always obvious to get a good grasp on what is the best way 
to  code a feature.
As a developer, and even though I love how concise Clojure programs can be, 
I am very concerned with readability and ease of maintenance so I would 
like to keep functions as short and tight as possible, but not to the point 
where it becomes hard to understand what it does.

Here is a function that I came up with that takes  a bpm (heart beats per 
minute) value, as well as a sequence of 4 values that represent the 
boundaries defining the 5 different heart rate zones for a particular 
person.
The function needs to finds out in what heart zone the bpm value falls into 
and return that zone (as a keyword - I later use that keyword in a map).

If you're an experienced Clojure developer, what would you have done 
differently (and why) ?

*(defn hr-zone*
*  "Return the HR zone as a keyword according to the bpm value."*
*  [bpm [max-zone-1 max-zone-2 max-zone-3 max-zone-4]] *
*  (cond *
*(<= bpm max-zone-1) :hr-zone-1*
*(and (< max-zone-1 bpm) (>= max-zone-2 bpm)) :hr-zone-2 *
*(and (< max-zone-2 bpm) (>= max-zone-3 bpm)) :hr-zone-3 *
*(and (< max-zone-3 bpm) (>= max-zone-4 bpm)) :hr-zone-4 *
*(< max-zone-4 bpm) :hr-zone-5))*

FYI, here is how I call this function in the REPL:
(def my-hr-zones-defs [120 150 165 180])

(hr-zone 115 my-hr-zones-defs)
(hr-zone 133 my-hr-zones-defs)
(hr-zone 161 my-hr-zones-defs)
(hr-zone 175 my-hr-zones-defs)
(hr-zone 192 my-hr-zones-refs)

Questions I have:
Would that make sense to consider (and maybe enforce) that the sequence 
received as parameter is sorted? If this was the case, I would assume I 
could avoid the "and" calls- assuming that all the conditions in the cone 
form are evaluated in order. 
Assuming that I need to test bpm against the two boundaries of each range, 
would there be a better way to do this:
*(and (< max-zone-1 bpm) (>= max-zone-2 bpm))*
?
Maybe this would work, but is it preferable?
*(< max-zone-1 bpm (dec **max-zone-2**))*

*Thanks in advance for the advice.*

*Laurent. *

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

  * can synchronize across multiple pieces of data

but has the disadvantage of:

  * work must be "pure" since it can be retried

  * possibly less efficient due to possibility of retrying


In the example I posted above, I only need to:

  * modify a single atom

and the approach I presented above:

  * can be impure, since it is guaranteed to only run once

  * is guaranteed to succeed (without retrys)

On Sun, Feb 16, 2014 at 2:25 PM, Ramesh  wrote:
> You can use a ref instead of an atom. And use dosync with multiple alter, so
> everything is safely inside a transaction.
>
> On Feb 16, 2014 2:04 PM, "t x"  wrote:
>>
>> Hi John,
>>
>>   Your solution is perfectly valid and optimal for the problem I
>> described above.
>>
>>
>>   Unfortunately, I forgot to mention an additional constraint: sometimes I
>> do:
>>
>> (let [ foo (:some-selector @data-atom) ]
>>   (swap! data-atom update-in [:other-selector] ... ))
>>
>> which the -> doesn't quite work on, but my ugly hack above does resolve.
>>
>>
>>   The problem being -- I want to update one part of the atom, but it
>> depends on another part of the atom.
>>
>>   I ended up with the following hack:
>>
>> (defn tswap! [atm func]
>>   (swap! atm
>>  (fn [old]
>>(let [natm (atom old)]
>>  (func natm)
>>  @natm
>>
>>
>> On Sat, Feb 15, 2014 at 4:09 PM, John D. Hume 
>> wrote:
>> > 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.
>>
>> --
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clojure@googlegroups.com
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+unsubscr...@googlegroups.com
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Clojure" group.
>> To unsubscribe from 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.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from 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.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from 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-16 Thread Ramesh
You can use a ref instead of an atom. And use dosync with multiple alter,
so everything is safely inside a transaction.
On Feb 16, 2014 2:04 PM, "t x"  wrote:

> Hi John,
>
>   Your solution is perfectly valid and optimal for the problem I
> described above.
>
>
>   Unfortunately, I forgot to mention an additional constraint: sometimes I
> do:
>
> (let [ foo (:some-selector @data-atom) ]
>   (swap! data-atom update-in [:other-selector] ... ))
>
> which the -> doesn't quite work on, but my ugly hack above does resolve.
>
>
>   The problem being -- I want to update one part of the atom, but it
> depends on another part of the atom.
>
>   I ended up with the following hack:
>
> (defn tswap! [atm func]
>   (swap! atm
>  (fn [old]
>(let [natm (atom old)]
>  (func natm)
>  @natm
>
>
> On Sat, Feb 15, 2014 at 4:09 PM, John D. Hume 
> wrote:
> > 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.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from 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.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from 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-16 Thread Karsten Schmidt
Yer welcome & please do let me know how this works out for you! I've
updated the gist[1] to delay more parts of the whole computation and
replace most occurrences of `reduce` with `loop` - altogether leading
to an almost 2x faster result for the worst case scenario where all
test clauses are checked. K.

[1] https://gist.github.com/postspectacular/9021724

On 15 February 2014 17:25, Lee Spector  wrote:
>
>
> 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.



-- 
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: (series of swap! on atom) ==> single swap!

2014-02-16 Thread t x
Hi John,

  Your solution is perfectly valid and optimal for the problem I
described above.


  Unfortunately, I forgot to mention an additional constraint: sometimes I do:

(let [ foo (:some-selector @data-atom) ]
  (swap! data-atom update-in [:other-selector] ... ))

which the -> doesn't quite work on, but my ugly hack above does resolve.


  The problem being -- I want to update one part of the atom, but it
depends on another part of the atom.

  I ended up with the following hack:

(defn tswap! [atm func]
  (swap! atm
 (fn [old]
   (let [natm (atom old)]
 (func natm)
 @natm


On Sat, Feb 15, 2014 at 4:09 PM, John D. Hume  wrote:
> 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.

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

2014-02-16 Thread Gary Trakhman
I was inches away from reinventing something like this for our company's
codebase.  Maybe you saved us the trouble :-).

Will definitely check it out.


On Sun, Feb 16, 2014 at 3:20 PM, Tommi Reiman wrote:

> Hi all.
>
> We here at Metosin have been developing and using a bunch of small
> utilities for Ring-based web api development. Here they are:
>
> *1) ring-http-response *(https://github.com/metosin/ring-http-response)
>
> Real http status codes for Ring - ported from Spray[1]. There is a
> response function for most of the http-statuses available (ok, found,
> not-found,...) taking either a body, url or nothing as a parameter. In
> addition, for all erroneous responses there is a exception throwing version
> with '!' in the end (bad-request!, not-found!,...). There is also a
> middleware for catching these response exceptions and returning the thrown
> http-response instead. Namespace *ring.util.http-response* can be used to
> replace the original *ring.util.response*.
>
> Should be stable.
>
> *2) ring-swagger* (https://github.com/metosin/ring-swagger)
>
> We wanted there to be a standalone Swagger[2] implementation for Ring, not
> tied to the used routing library. There is already Swag[3] and
> Octohipster[4], but both have strong opinions about routing. Ring-Swagger
> is integrated with Prismatic Schema for data modeling & coercing (should it
> support other validation libs also?). Offers a simple map-based api for
> routing & other higher level web libs to publish their routes.
>
> There is an adapter for Compojure on top of this, more later.
>
> Would be fun to other routing/web libs adapt to this too (should be quite
> straightforward to collect routes from bidi for example)
>
> Not yet feature complete. All feedback & Pull Requests welcome.
>
> *3) ring-swagger-ui* (https://github.com/metosin/ring-swagger-ui)
>
> Maven-packaged version of the Swagger-UI[5]. Follows the version numbers
> of the original npm packages (permission to publish as maven artifact from
> the Reverb guys, thanks guys!). Has some small changes in the ui. All stuff
> can be overridden locally (mainly the index page).
>
> *4) compojure-api* (https://github.com/metosin/compojure-api)
>
> Originally was supposed to be just compojure-swagger, but added other
> stuff to make life of an web api development easier. Everything can be used
> separately, but there is also a *compojure.api.sweet* package, which can
> be used as a single entry point to the library.
>
> Basic Swagger-functionality works with vanilla Compojure but to enable all
> features (better way to setup route meta-data, schema-aware body
> destructuring, return schemas etc.), there is a extended api, with '*' in
> the name of the http-methods (GET*, POST*). Currently the extended api is
> also sitting on top of Compojure and internally overrides a compile-route
> function from *compojure.core* to enable easy way to add meta-data to
> routes. Thinking of re-implementing the new api directly on top of Clout
> instead of trying to sit on top of the (otherwise awesome) Compojure.
>
> Currently work in progress. Acts also as a demo how to use & bind together
> the underlying more stable libs (ring-http-response, ring-swagger
> &ring-swagger-ui).
>
> *5) compojure-api-examples* (
> https://github.com/metosin/compojure-api-examples)
>
> A sample minimalistic project to see things in action and to start
> creating schema-aware documented web apis.
>
> ...
>
> Hopefully some of the stuff is found useful, on both Github & Clojars. We
> are using (and developing) these anyway with our projects. Also waiting
> eagerly for the @PrismaticEng next web thingie coming out soon(?), whether
> these libs complement or overlap each other.
>
> Would appreciate your comments and thoughts on the concepts or the code.
> Either here or via email: first-name (at) metosin.fi or ikitommi at
> freenode & twitter.
>
> regards,
>
> Tommi
>
> --
>
> [1] http://spray.io
> [2] https://github.com/wordnik/swagger-core/wiki
> [3] https://github.com/narkisr/swag
> [4] https://github.com/myfreeweb/octohipster
> [5] https://github.com/wordnik/swagger-ui
>
>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from 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.
>

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

ANN: ring-http-response, ring-Swagger, ring-swagger-ui & compojure-api

2014-02-16 Thread Tommi Reiman
Hi all.

We here at Metosin have been developing and using a bunch of small 
utilities for Ring-based web api development. Here they are:

*1) ring-http-response *(https://github.com/metosin/ring-http-response)

Real http status codes for Ring - ported from Spray[1]. There is a response 
function for most of the http-statuses available (ok, found, not-found,...) 
taking either a body, url or nothing as a parameter. In addition, for all 
erroneous responses there is a exception throwing version with '!' in the 
end (bad-request!, not-found!,...). There is also a middleware for catching 
these response exceptions and returning the thrown http-response instead. 
Namespace *ring.util.http-response* can be used to replace the original 
*ring.util.response*.

Should be stable.

*2) ring-swagger* (https://github.com/metosin/ring-swagger)

We wanted there to be a standalone Swagger[2] implementation for Ring, not 
tied to the used routing library. There is already Swag[3] and 
Octohipster[4], but both have strong opinions about routing. Ring-Swagger 
is integrated with Prismatic Schema for data modeling & coercing (should it 
support other validation libs also?). Offers a simple map-based api for 
routing & other higher level web libs to publish their routes.

There is an adapter for Compojure on top of this, more later.

Would be fun to other routing/web libs adapt to this too (should be quite 
straightforward to collect routes from bidi for example)

Not yet feature complete. All feedback & Pull Requests welcome.

*3) ring-swagger-ui* (https://github.com/metosin/ring-swagger-ui)

Maven-packaged version of the Swagger-UI[5]. Follows the version numbers of 
the original npm packages (permission to publish as maven artifact from the 
Reverb guys, thanks guys!). Has some small changes in the ui. All stuff can 
be overridden locally (mainly the index page).

*4) compojure-api* (https://github.com/metosin/compojure-api)

Originally was supposed to be just compojure-swagger, but added other stuff 
to make life of an web api development easier. Everything can be used 
separately, but there is also a *compojure.api.sweet* package, which can be 
used as a single entry point to the library.

Basic Swagger-functionality works with vanilla Compojure but to enable all 
features (better way to setup route meta-data, schema-aware body 
destructuring, return schemas etc.), there is a extended api, with '*' in 
the name of the http-methods (GET*, POST*). Currently the extended api is 
also sitting on top of Compojure and internally overrides a compile-route 
function from *compojure.core* to enable easy way to add meta-data to 
routes. Thinking of re-implementing the new api directly on top of Clout 
instead of trying to sit on top of the (otherwise awesome) Compojure.

Currently work in progress. Acts also as a demo how to use & bind together 
the underlying more stable libs (ring-http-response, ring-swagger 
&ring-swagger-ui).

*5) compojure-api-examples* (
https://github.com/metosin/compojure-api-examples)

A sample minimalistic project to see things in action and to start creating 
schema-aware documented web apis.

...

Hopefully some of the stuff is found useful, on both Github & Clojars. We 
are using (and developing) these anyway with our projects. Also waiting 
eagerly for the @PrismaticEng next web thingie coming out soon(?), whether 
these libs complement or overlap each other.

Would appreciate your comments and thoughts on the concepts or the code. 
Either here or via email: first-name (at) metosin.fi or ikitommi at 
freenode & twitter.

regards,

Tommi

--

[1] http://spray.io
[2] https://github.com/wordnik/swagger-core/wiki
[3] https://github.com/narkisr/swag
[4] https://github.com/myfreeweb/octohipster
[5] https://github.com/wordnik/swagger-ui

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from 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-16 Thread The Dude (Abides)
You're right :) When I isolated the issue thanks to some help it turns out 
java.jdbc is working fine but I wasn't getting the resultset output 
properly in the function. So got it resolved and working like this:

(defn get-member [id]
(let [id (parse-int id)
  member (first (jdbc/query db ["SELECT id, username, firstname, 
lastname, email FROM members WHERE id = ? ORDER BY id ASC LIMIT 1" id]))]
(session/put! :member member)
(session/put! :next (+ id 1))
(layout/render "member/profile2.html" {:member member})))

So java.jdbc working just fine, able to get the results, set in session, 
etc. Thanks for all the feedback. 

On Saturday, February 15, 2014 9:55:16 PM UTC-8, edbond wrote:
>
> 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.Select

Re: rseq for subvec in clojurescript

2014-02-16 Thread Michał Marczyk
It is now, thanks for the report!

Ticket with patch:

http://dev.clojure.org/jira/browse/CLJS-765


On 16 February 2014 17:48, Sunil S Nandihalli
 wrote:
> Hi Everybody,
>
> I get the following error when I do a rseq on a subvec in clojurescript
> Uncaught Error: No protocol method IReversible.-rseq defined for type
> cljs.core/Subvec: [(:red :clockwise) (:blue :clockwise) (:yellow :clockwise)
> (:yellow :clockwise) (:orange :clockwise)]
>
> Is this a known problem?
> Thanks, Sunil
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from 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.

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

2014-02-16 Thread Ambrose Bonnaire-Sergeant
Hi,

Happy to announce the first version of
typed-clojure-mode,
an emacs
minor mode for Typed Clojure.

Thanks to John Walker who wrote the core functionality, he earned this open
source 
bountyfor
his work.

I'll be maintaining typed-clojure-mode from here, please open an
issueor get
in touch if something is broken or missing.

Thanks,
Ambrose

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from 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-16 Thread Alex Walker
Part of Rich's objection to not-nil? variants could be that they are a 
double negative, "not-(no value)?", which can decrease clarity and require 
more coffee.


>- nil Means 'nothing/no-value'- represents Java null and tests logical 
>false [clojure.org/reader]
>
>
To compete with some? variants, I'd suggest a positive that I found 
strangely available:

exists?
if-exists[?]
when-exists[?]

Or, more proper, though potentially more overloaded: value?, if-value[?], 
when-value[?].

On Sunday, February 16, 2014 12:54:12 AM UTC-6, Эльдар Габдуллин wrote:
>
> 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.


rseq for subvec in clojurescript

2014-02-16 Thread Sunil S Nandihalli
Hi Everybody,

I get the following error when I do a rseq on a subvec in clojurescript
Uncaught Error: No protocol method IReversible.-rseq defined for type
cljs.core/Subvec: [(:red :clockwise) (:blue :clockwise) (:yellow
:clockwise) (:yellow :clockwise) (:orange :clockwise)]

Is this a known problem?
Thanks, Sunil

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

2014-02-16 Thread Olli Piepponen
This looks very neat, but I was unable to figure out how to use 
lispy/clojure-semantic the way you were doing in your screencast. Could you 
give a breakdown of how this works?

On Saturday, February 15, 2014 4:46:48 AM UTC+7, Oleh wrote:
>
> Hi all,
>
> As a follow-up to this post - 
> https://groups.google.com/forum/#!topic/clojure/B7dTW5PDcPM,
> it's now possible to jump to any Clojure tag in current directory.
> No project definitions required: CEDET will parse every source file in 
> current directory.
> The tags are completed with helm plugin, so it's quite fast to find a 
> candidate to jump to.
>
> As a showcase, I've took this popular Clojure statistics package: 
> https://github.com/liebke/incanter
>
> The screencast is here: https://vimeo.com/86727658.
>
> lispy is here: https://github.com/abo-abo/lispy
> clojure-semantic is here: https://github.com/kototama/clojure-semantic
>
> There's currently a bug in clojure-semantic the prevents permanent storage 
> of parsed tags,
> maybe someone with some expertise could look into that. 
> Also, it's generated by a bison-like grammar, so if you know bison (I 
> don't unfortunately),
> you could extend clojure-semantic to distinguish stuff like defmacro, 
> defmulti, defmethod etc.
>
> Same functionality is also available for Emacs Lisp, Scheme and Common 
> Lisp, if you like using
> anything else besides Clojure:)
>
> regards,
> Oleh
>

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


Some advice about introducing clojurescript into a project using js/jquery

2014-02-16 Thread Kashyap CK
Hi,

It took me some time to get started with clojurescript (on windows/cygwin) 
- http://swannodette.github.io/2013/11/07/clojurescript-101/ worked for me.

I'd like to use clojurescript to do some UI component development for 
product which is built using webkit/js/jquery. I was wondering if it is 
okay to develop a feature in such an application, where most of the UI is 
in jquery, in clojurescript?

I'd appreciate it very much to know if there are any known gotha's here or 
any tips that I could use?  

Regards,
Kashyap

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

2014-02-16 Thread James Reeves
Symbols are used in Clojure to represent identifiers, and in this case
we're identifying a namespace.

I believe it's also the case that a valid symbol is also a valid namespace
name.

- James


On 16 February 2014 10:39, Andy Smith  wrote:

>
> (require 'clojure.string)
>
> Im just wondering why the language chose to use the quote form, rather
> than a string or a keyword e.g.
>
>
> (require "clojure.string")
>
> (require :clojure.string)
>
> There obviously must be a good reason why.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from 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.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from 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-16 Thread Jules
Thinking about it a bit more, it would be good to have an interface e.g. 
Spliceable which e.g. 'into' could take advantage of when it found itself 
concatenating two seq of the same implementation...

Further digging might demonstrate that a similar trick could be used with 
other seq types ?

Splice currently only supports 2 params - splice(left, right). If you could 
splice(lhs, rhses...) then I think it could be used more efficiently in a 
reducers combination phase... I would like to be able to recombine the 
subresults of multiple cores in a single iteration.

Finally, I would also be keen to investigate my idea about the efficient 
'cleave'-ing of tree-based seqs so that they can be used as inputs to the 
reducers library, as mentioned in my original post...


Jules


On Sunday, 16 February 2014 10:57:35 UTC, Jules wrote:
>
> I would have thought so - it's only my first cut - seems to work but I 
> wouldn't like to stake my life on it. It really needs a developer who is 
> familiar with PersistentHashMap to look it over and give it the thumbs 
> up...Still, I guess if it was marked "experimental" ...:-)
>
> Jules
>
>
> On Sunday, 16 February 2014 10:49:38 UTC, Mikera wrote:
>>
>> Wow - that's a pretty big win. I think we should try and get this into 
>> Clojure ASAP.
>>
>> Are we too late for 1.6?
>>
>> On Sunday, 16 February 2014 18:48:09 UTC+8, Jules wrote:
>>>
>>> Thanks, Mikera
>>>
>>> You are right about merge:
>>>
>>> user=> (def m1 (apply hash-map (range 1000)))
>>> #'user/m1
>>> user=> (def m2 (apply hash-map (range 500 1500)))
>>> #'user/m2
>>> user=> (time (def m3 (merge m1 m2)))
>>> "Elapsed time: 5432.184582 msecs"
>>> #'user/m3
>>> user=> (time (def m4 (clojure.lang.PersistentHashMap/splice m1 m2)))
>>> "Elapsed time: 1064.268269 msecs"
>>> #'user/m4
>>> user=> (= m3 m4)
>>> true
>>> user=> 
>>>
>>> as you would expect, a splice is faster and causes less of a memory 
>>> spike.
>>>
>>>
>>> Jules
>>>
>>>
>>> On Sunday, 16 February 2014 10:01:04 UTC, Mikera wrote:

 +1 for this approach - I've wanted something like this several times.

 It's only an "optimisation", but it's a very useful one. Same technique 
 can probably be used to accelerate "merge" significantly  which is a 
 pretty 
 common operation when you are building map-like structures.

 On Sunday, 16 February 2014 07:06:24 UTC+8, 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 o

Re: fast parallel reduction into hash-set/map

2014-02-16 Thread Jules
I would have thought so - it's only my first cut - seems to work but I 
wouldn't like to stake my life on it. It really needs a developer who is 
familiar with PersistentHashMap to look it over and give it the thumbs 
up...Still, I guess if it was marked "experimental" ...:-)

Jules


On Sunday, 16 February 2014 10:49:38 UTC, Mikera wrote:
>
> Wow - that's a pretty big win. I think we should try and get this into 
> Clojure ASAP.
>
> Are we too late for 1.6?
>
> On Sunday, 16 February 2014 18:48:09 UTC+8, Jules wrote:
>>
>> Thanks, Mikera
>>
>> You are right about merge:
>>
>> user=> (def m1 (apply hash-map (range 1000)))
>> #'user/m1
>> user=> (def m2 (apply hash-map (range 500 1500)))
>> #'user/m2
>> user=> (time (def m3 (merge m1 m2)))
>> "Elapsed time: 5432.184582 msecs"
>> #'user/m3
>> user=> (time (def m4 (clojure.lang.PersistentHashMap/splice m1 m2)))
>> "Elapsed time: 1064.268269 msecs"
>> #'user/m4
>> user=> (= m3 m4)
>> true
>> user=> 
>>
>> as you would expect, a splice is faster and causes less of a memory spike.
>>
>>
>> Jules
>>
>>
>> On Sunday, 16 February 2014 10:01:04 UTC, Mikera wrote:
>>>
>>> +1 for this approach - I've wanted something like this several times.
>>>
>>> It's only an "optimisation", but it's a very useful one. Same technique 
>>> can probably be used to accelerate "merge" significantly  which is a pretty 
>>> common operation when you are building map-like structures.
>>>
>>> On Sunday, 16 February 2014 07:06:24 UTC+8, 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

Re: fast parallel reduction into hash-set/map

2014-02-16 Thread Mikera
Wow - that's a pretty big win. I think we should try and get this into 
Clojure ASAP.

Are we too late for 1.6?

On Sunday, 16 February 2014 18:48:09 UTC+8, Jules wrote:
>
> Thanks, Mikera
>
> You are right about merge:
>
> user=> (def m1 (apply hash-map (range 1000)))
> #'user/m1
> user=> (def m2 (apply hash-map (range 500 1500)))
> #'user/m2
> user=> (time (def m3 (merge m1 m2)))
> "Elapsed time: 5432.184582 msecs"
> #'user/m3
> user=> (time (def m4 (clojure.lang.PersistentHashMap/splice m1 m2)))
> "Elapsed time: 1064.268269 msecs"
> #'user/m4
> user=> (= m3 m4)
> true
> user=> 
>
> as you would expect, a splice is faster and causes less of a memory spike.
>
>
> Jules
>
>
> On Sunday, 16 February 2014 10:01:04 UTC, Mikera wrote:
>>
>> +1 for this approach - I've wanted something like this several times.
>>
>> It's only an "optimisation", but it's a very useful one. Same technique 
>> can probably be used to accelerate "merge" significantly  which is a pretty 
>> common operation when you are building map-like structures.
>>
>> On Sunday, 16 February 2014 07:06:24 UTC+8, 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

Re: fast parallel reduction into hash-set/map

2014-02-16 Thread Jules
Thanks, Mikera

You are right about merge:

user=> (def m1 (apply hash-map (range 1000)))
#'user/m1
user=> (def m2 (apply hash-map (range 500 1500)))
#'user/m2
user=> (time (def m3 (merge m1 m2)))
"Elapsed time: 5432.184582 msecs"
#'user/m3
user=> (time (def m4 (clojure.lang.PersistentHashMap/splice m1 m2)))
"Elapsed time: 1064.268269 msecs"
#'user/m4
user=> (= m3 m4)
true
user=> 

as you would expect, a splice is faster and causes less of a memory spike.


Jules


On Sunday, 16 February 2014 10:01:04 UTC, Mikera wrote:
>
> +1 for this approach - I've wanted something like this several times.
>
> It's only an "optimisation", but it's a very useful one. Same technique 
> can probably be used to accelerate "merge" significantly  which is a pretty 
> common operation when you are building map-like structures.
>
> On Sunday, 16 February 2014 07:06:24 UTC+8, 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 / cloju

Re: NetBeans?

2014-02-16 Thread Rui Carmo
In case anyone's interested, I've picked up Geertjan's stuff and started a 
repo at https://github.com/rcarmo/netbeans-clojure, since it's minimally 
usable already.

There's a tentative roadmap there as well -- feel free to ping me directly 
if you want commit access.

Regards,

R.

On Friday, February 14, 2014 11:49:09 AM UTC, Rui Carmo wrote:
>
> Hi there,
>
> I've been using LightTable daily (and vim) for my Clojure stuff, but I'm 
> now finding myself having to use NetBeans in order to better manage a 
> number of existing Java-related sub-projects.
>
> It's not a matter of language choice, but of environment uniformity (I 
> need to use the same tools as other folk).
>
> So I would love to have modern, working Clojure support in NetBeans.
>
> I've tracked down Enclojure (which is deprecated) and came across 
> Geertjan's blog entry here:
>
> https://blogs.oracle.com/geertjan/entry/leiningen_clojure_and_netbeans_ide
>
> ...but that is still a work in progress, and even though I've checked out 
> his SVN, it still requires time to figure out how to build the plugin.
>
> Since there's a GSOC coming up, has anyone suggested putting this up as a 
> project idea? 
>
> I find it somewhat sad that NetBeans has great Scala support and 
> effectively zero Clojure support, and think there should be a 
> community-wide effort to even the balance.
>
> Regards,
>
> R.
>

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

2014-02-16 Thread Andy Smith

(require 'clojure.string)

Im just wondering why the language chose to use the quote form, rather than 
a string or a keyword e.g.


(require "clojure.string")

(require :clojure.string)

There obviously must be a good reason why. 

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

It's only an "optimisation", but it's a very useful one. Same technique can 
probably be used to accelerate "merge" significantly  which is a pretty 
common operation when you are building map-like structures.

On Sunday, 16 February 2014 07:06:24 UTC+8, 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 s

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

2014-02-16 Thread gianluca torta
as a side note, since we are within the backquote, simply using r (instead 
of ~'r) would not work since it would incorrectly expand to the fully 
qualified symbol, e.g. user/r

Gianluca

On Saturday, February 15, 2014 5:49:57 PM UTC+1, Jan Herich wrote:
>
> 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.