Re: printf output from threads
seems there's no type hint required: (def t nil) (Thread. t) also works... How are you able to determine that it's calling the String constructor? --Robert McIntyre On Tue, Dec 28, 2010 at 3:08 AM, Alex Osborne a...@meshy.org wrote: Robert McIntyre r...@mit.edu writes: what the heck... mailing-list.print-from-threads (Thread. ((constantly nil))) #Thread Thread[Thread-100,5,main] mailing-list.print-from-threads (Thread. ((fn []))) #Thread Thread[Thread-101,5,main] mailing-list.print-from-threads (Thread. ((fn [] nil))) #Thread Thread[Thread-102,5,main] mailing-list.print-from-threads (Thread. (let [this-is-nil ((fn [] nil))] this-is-nil)) #Thread Thread[Thread-103,5,main] mailing-list.print-from-threads (Thread. nil) ; Evaluation aborted. mailing-list.print-from-threads (= nil (let [this-is-nil ((fn [] nil))] this-is-nil) ((fn [])) ((constantly nil))) true mailing-list.print-from-threads all of these things are referentially transparent, so how is clojure differentiating between things that evaluate to nil and nil itself? It's picking the Thread(String name), constructor for some reason when it gets an Object type hint. user (let [^Object o nil] (Thread. o)) #Thread Thread[Thread-8,5,main] -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: printf output from threads
Robert McIntyre r...@mit.edu writes: seems there's no type hint required: (def t nil) (Thread. t) also works... How are you able to determine that it's calling the String constructor? --Robert McIntyre Ah, no I'm wrong. I was jumping to conclusions. It's the Runnable one: (let [^String o nil] (Thread. o)) ; error (let [^Runnable o nil] (Thread. o)) ; no error -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: printf output from threads
Robert McIntyre r...@mit.edu writes: So there's some sort of boxing going on here where the nil produced as the values of s-expressions are actually Objects which are nulls, while literal nils are actually nulls? No, there's no boxing going on. They're both just regular Java nulls (and null is not an Object). The only difference is in the byte code generation: which constructor gets picked (if any). It seems as if the runtime reflection code when encountering a null will just pick the first constructor it sees, while the compile-time code notices the ambiguity and throws an error. It's kind of annoying that you can't type-hint the nil too. (Thread. ^Runnable nil) ; error, nil can't hold metadata and have to resort to binding it and hinting the binding. (let [^Runnable s nil] (Thread. s)) ; ok Such as in java where: Object t = null; Thread r = new Thread((String) t); is valid but Thread r = new Thread(null); is not ? In this case you've explicitly told Java the type with a string cast so it can generate bytecode that refers the String constructor. You can do that directly too: Thread r = new Thread((String) null); Being statically typed Java never does runtime reflection (unless you explicitly code it) so this issue cannot actually arise in it. Isn't this breaking referential transparency that (Thread. ((fn []))) and (Thread. nil) are not the same (you can't replace a function call with it's value in this case)? This is not the behaviour I would expect at all, as it would make any clojure function with a nil in it's range no longer pure. Ambiguous code is arguably invalid in some sense anyway when running on a deterministic machine model, so I'm not sure it makes sense to talk about the purity of it. Suppose I do this and never actually call the resulting fn, just throw it away: #(Thread. nil) ; throws an error at compile time #(Thread. (identity nil)) ; doesn't and can't How could they be made consistent? I guess either: 1) Resolve the ambiguity by consistently picking one of the constructors (perhaps the first alphabetically). 2) Delay the exception throwing in the direct nil case to runtime, so the compiler would replace the form with: #(throw (java.lang.IllegalArgumentException.)) And have the reflection code in the second detect ambiguity and throw at runtime as well. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Quicksort with accumulator
Hello, I tried writing a naive implementation of quicksort using an accumulator. Right now, the code is stack-consuming and returns a stackoverflowerror on large lists. Is there any way to prevent it from consuming stack with some changes? The code is as follows - (declare qsort qsort* partify) (defn partify [item coll [less equal greater] acc] (if (empty? coll) (qsort* less (concat equal (qsort* greater acc))) (let [[head tail] coll] (cond ( head item) (recur item tail [(cons head less) equal greater] acc) ( head item) (recur item tail [less equal (cons head greater)] acc) :else (recur item tail [less (cons head equal) greater] acc) (defn qsort* [coll acc] (if-let [coll (seq coll)] (partify (first coll) (rest coll) [[] [(first coll)] []] acc) acc)) (defn qsort Perform Quicksort, with apologies to C.A.R. Hoare [coll] (if-let [coll (seq coll)] (qsort* coll []) [])) Regards, BG -- Baishampayan Ghose b.ghose at gmail.com -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: printf output from threads
On Dec 27, 10:59 pm, Alex Osborne a...@meshy.org wrote: justinhj justi...@gmail.com writes: On Dec 26, 11:42 pm, Alex Osborne a...@meshy.org wrote: (defn test-threads [n out] (dotimes [x n] (.start (Thread. (#(sleeper-thread %1 %2 %3) out x (+ 2000 (rand- int 5000))) Ah. The problem is here. You're calling that lambda in the main thread and then passing the return value of sleeper-thread to (Thread.) (which doesn't make much sense). Try this: (defn test-threads [n out] (dotimes [x n] (.start (Thread. #(sleeper-thread out x (+ 2000 (rand-int 5000))) Or even: (defn test-threads [n out] (dotimes [x n] (future (sleeper-thread out x (+ 2000 (rand-int 5000)) Or forgetting about passing the out argument around: (defn test-threads [n] (dotimes [x n] (let [out *out*] (future (binding [*out* out] (sleeper-thread x (+ 2000 (rand-int 5000)) You could turn that into a macro: (defmacro future-with-out [ body] `(let [out# *out*] (future (binding [*out* out#] ~...@body))) And then use it like: (defn test-threads [n] (dotimes [x n] (future-with-out (sleeper-thread x (+ 2000 (rand-int 5000)) Thanks Alex, I'm still struggling a bit with the different syntax between Clojure and Common Lisp, but I made your first change and it works now. Justin -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Quicksort with accumulator
Why do you call qsort* inside of partify? I do not really grasp your logic behind this. On Tue, Dec 28, 2010 at 8:20 PM, Baishampayan Ghose b.gh...@gmail.com wrote: Hello, I tried writing a naive implementation of quicksort using an accumulator. Right now, the code is stack-consuming and returns a stackoverflowerror on large lists. Is there any way to prevent it from consuming stack with some changes? The code is as follows - (declare qsort qsort* partify) (defn partify [item coll [less equal greater] acc] (if (empty? coll) (qsort* less (concat equal (qsort* greater acc))) (let [[head tail] coll] (cond ( head item) (recur item tail [(cons head less) equal greater] acc) ( head item) (recur item tail [less equal (cons head greater)] acc) :else (recur item tail [less (cons head equal) greater] acc) (defn qsort* [coll acc] (if-let [coll (seq coll)] (partify (first coll) (rest coll) [[] [(first coll)] []] acc) acc)) (defn qsort Perform Quicksort, with apologies to C.A.R. Hoare [coll] (if-let [coll (seq coll)] (qsort* coll []) [])) Regards, BG -- Baishampayan Ghose b.ghose at gmail.com -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- Petr Gladkikh -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Quicksort with accumulator
And also qsort may take up to n stack frames for collection of n elements if you partition function is not optimal. In your case - if input collection is sorted (as long as you split by first element). On Tue, Dec 28, 2010 at 11:13 PM, Petr Gladkikh petrg...@gmail.com wrote: Why do you call qsort* inside of partify? I do not really grasp your logic behind this. On Tue, Dec 28, 2010 at 8:20 PM, Baishampayan Ghose b.gh...@gmail.com wrote: Hello, I tried writing a naive implementation of quicksort using an accumulator. Right now, the code is stack-consuming and returns a stackoverflowerror on large lists. Is there any way to prevent it from consuming stack with some changes? The code is as follows - (declare qsort qsort* partify) (defn partify [item coll [less equal greater] acc] (if (empty? coll) (qsort* less (concat equal (qsort* greater acc))) (let [[head tail] coll] (cond ( head item) (recur item tail [(cons head less) equal greater] acc) ( head item) (recur item tail [less equal (cons head greater)] acc) :else (recur item tail [less (cons head equal) greater] acc) (defn qsort* [coll acc] (if-let [coll (seq coll)] (partify (first coll) (rest coll) [[] [(first coll)] []] acc) acc)) (defn qsort Perform Quicksort, with apologies to C.A.R. Hoare [coll] (if-let [coll (seq coll)] (qsort* coll []) [])) Regards, BG -- Baishampayan Ghose b.ghose at gmail.com -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- Petr Gladkikh -- Petr Gladkikh -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Quicksort with accumulator
On Tue, 28 Dec 2010 19:50:28 +0530 Baishampayan Ghose b.gh...@gmail.com wrote: Hello, I tried writing a naive implementation of quicksort using an accumulator. Right now, the code is stack-consuming and returns a stackoverflowerror on large lists. Is there any way to prevent it from consuming stack with some changes? The code is as follows - You don't say what your test data is, but pretty much any quicksort implementation will have some nasty test cases for which its memory usage is nasty and its performance is worse. Given that this is a simple implementation, data that is already sorted is the degenerate case. I don't think you can keep it from using any stack - a non-recursive implementation would just have to maintain it's own stack state. You can do some things to make it use less stack, though. First, deal with sorted data better by picking a median value from coll instead of the first one. Once the sequences get small enough, change to a non-recursive sorting method to sort them. If you're up to serious refactoring, fix the code to generate the partitions inside of qsort*, and then use recur for the tail call of qsort* - and make sure that call is on longer of less and greater. mike (declare qsort qsort* partify) (defn partify [item coll [less equal greater] acc] (if (empty? coll) (qsort* less (concat equal (qsort* greater acc))) (let [[head tail] coll] (cond ( head item) (recur item tail [(cons head less) equal greater] acc) ( head item) (recur item tail [less equal (cons head greater)] acc) :else (recur item tail [less (cons head equal) greater] acc) (defn qsort* [coll acc] (if-let [coll (seq coll)] (partify (first coll) (rest coll) [[] [(first coll)] []] acc) acc)) (defn qsort Perform Quicksort, with apologies to C.A.R. Hoare [coll] (if-let [coll (seq coll)] (qsort* coll []) [])) Regards, BG -- Mike Meyer m...@mired.org http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O ascii ribbon campaign - stop html mail - www.asciiribbon.org -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Quicksort with accumulator
I tried writing a naive implementation of quicksort using an accumulator. Right now, the code is stack-consuming and returns a stackoverflowerror on large lists. Is there any way to prevent it from consuming stack with some changes? The code is as follows - You don't say what your test data is, but pretty much any quicksort implementation will have some nasty test cases for which its memory usage is nasty and its performance is worse. Given that this is a simple implementation, data that is already sorted is the degenerate case. I don't think you can keep it from using any stack - a non-recursive implementation would just have to maintain it's own stack state. You can do some things to make it use less stack, though. This is just a toy implementation, not something real :) I am interested in learning about making this code truly tail recursive and/or lazy. Identical implementations on Haskell work just fine, so I wrote this one for some testing... When you try using some large numbers like 10 million, it blows the stack. A completely lazy solution is possible in Clojure, as shown in The Joy of Clojure. Regards, BG -- Baishampayan Ghose b.ghose at gmail.com -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Clojure Conj 2011?
fwiw - there was a number of lucky folks who I met at Strange Loop in St. Louis the week before Conj 2010 who were able to go to both. It seemed like there was quite a bit of overlap in interest of those two events. I could have probably gone to both if there was at least a few weeks time between the two. Scott Hickey (no relation) On Dec 27, 8:07 pm, Alan Dipert a...@dipert.org wrote: Hi, On Mon, Dec 27, 2010 at 7:41 PM, Sean Corfield seancorfi...@gmail.com wrote: Now that videos are being posted for the 2010 conj, I figured it might be worth asking if there has been any discussion about when/where the 2011 conj might happen? Conj 2011 will most likely be in either Raleigh or Durham, North Carolina, and probably will happen around the same time of year as the last Conj. We've reviewed all the feedback we've gotten, and are looking for a venue. Our hope is to announce the time and place as soon as possible. Sorry you couldn't make it to the last one, but looking forward to seeing you at the next one! Alan I had a schedule conflict last year (actually a double conflict) so I'd like to get this year's event on my calendar as early as possible so I don't miss it again :) -- Sean A Corfield -- (904) 302-SEAN Railo Technologies, Inc. --http://getrailo.com/ An Architect's View --http://corfield.org/ If you're not annoying somebody, you're not really alive. -- Margaret Atwood -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en- Hide quoted text - - Show quoted text - -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
osx + clojure + emacs + leiningen blog posts
oh hi, i put together a couple of blog posts around how i use clojure + emacs + leiningen on OSX (but applies to linux too) in the hope it may help someone get up and running faster: http://blog.gaz-jones.com/post/2486737162/setting-up-clojure-development-on-osx-using-emacs-and http://blog.gaz-jones.com/post/2501842155/interactive-clojure-development-in-emacs-with-leiningen suggestions for improvements / things im doing crazy are welcome! cheers gaz -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
From Binary Search Trees to the Dining Philosopher
Thanks Ken, Mark, David and Alex for your comments regarding Binary Search trees. I've read that thread several times, and ordered Okasaki's Purely Functional Data Structures, too. I'll return to this a bit later. Meanwhile, I decided to tackle learning Clojure from a different angle...in this case, implementing a solution for the Dining Philosopher problem. I've posted my code here: https://gist.github.com/757925 General comments/questions: 1. I suppose it's from years of OO programming, but it still feels so weird not to be creating objects and then hanging methods off those objects. In fact, my first approach was to create protocols and records for each of the 'objects': chopsticks, philosophers, even the table. But this started to get painful, so I shifted gears... 2. I'm using a number of symbols (:tablestate, :seats, :chopsticks, :servings, etc). Shouldn't these be defined somewhere? It feels like I'm driving w/o a seatbelt. I'm so used to encapsulating this sort of thing in an enum or something, and then relying on java typing to enforce the allowed values. 3. Starting a thread with (future ... This couldn't be easier. Very cool. 4. I tried making the table an agent instead of a ref. Then I was sending methods to the table like, start-tableservice or stop-tabelservice... I'll investigate further, but is it idiomatic to start threads within the agent? (BTW - Chapter 6 on State Management of Practical Clojure was particularly helpful to me for figuring out the syntax for refs and agents.) Anyone feel like tearing my code apart? I'd like to make it as clean and clojure-ish as possible. -Todd -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Clojure Conj 2011?
I have not yet set a date for Strange Loop (although I am talking to venues now). I'm currently looking at Sept 29-30 as the target date. JavaOne is the following week. Alex On Dec 28, 1:50 pm, scott jscotthic...@gmail.com wrote: fwiw - there was a number of lucky folks who I met at Strange Loop in St. Louis the week before Conj 2010 who were able to go to both. It seemed like there was quite a bit of overlap in interest of those two events. I could have probably gone to both if there was at least a few weeks time between the two. Scott Hickey (no relation) On Dec 27, 8:07 pm, Alan Dipert a...@dipert.org wrote: Hi, On Mon, Dec 27, 2010 at 7:41 PM, Sean Corfield seancorfi...@gmail.com wrote: Now that videos are being posted for the 2010 conj, I figured it might be worth asking if there has been any discussion about when/where the 2011 conj might happen? Conj 2011 will most likely be in either Raleigh or Durham, North Carolina, and probably will happen around the same time of year as the last Conj. We've reviewed all the feedback we've gotten, and are looking for a venue. Our hope is to announce the time and place as soon as possible. Sorry you couldn't make it to the last one, but looking forward to seeing you at the next one! Alan I had a schedule conflict last year (actually a double conflict) so I'd like to get this year's event on my calendar as early as possible so I don't miss it again :) -- Sean A Corfield -- (904) 302-SEAN Railo Technologies, Inc. --http://getrailo.com/ An Architect's View --http://corfield.org/ If you're not annoying somebody, you're not really alive. -- Margaret Atwood -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en-Hide quoted text - - Show quoted text - -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: can members of a defrecord be type hinted?
On Tue, Dec 28, 2010 at 2:58 AM, Sunil S Nandihalli sunil.nandiha...@gmail.com wrote: with my preliminary examination it seems like it does enhance storage efficiency and improve runtime performance.. How would still love to hear what you all have to say You are correct. Another nice thing - type hinted members do not need to be type hinted within defrecord method bodies. David -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Speed of clojure hash map vs java hash map
Just for fun, I was curious to see what it would be like, performance-wise, to simulate a synchronized mutable hash map by putting a clojure hash map inside an atom, and making this accessible to Java code via the map interface. I didn't try to implement the entire map interface, but just the major things for testing purposes. The code is below. Benchmarking insertions on my machine, I'm seeing that the Clojure code (Clojure 1.2, java -server) takes roughly 8-20x longer (depending on how large the hashmap is). To test, for example, I do something like (def ^com.justforfun.NonBlockingHashMap h (com.justforfun.NonBlockingHashMap.)) (def ^java.util.Map j (. java.util.Collections synchronizedMap (java.util.HashMap.))) (time (doseq [i (range 10)] (.put h i 2))) ;900ms (time (doseq [i (range 10)] (.put j i 2)));70ms Does this seem reasonable, or is there a better way to do this test? Frankly, I was expecting Clojure's numbers to compare a bit more favorably. If you repeat the run, shoving new values into the existing hash table, make sure to change the value you're sticking into the hash table (Clojure optimizes when you store the same value in the hash table that's already there). [Code] (ns com.justforfun.NonBlockingHashMap (:gen-class :implements [java.lang.Iterable] :init init :constructors {[] []} :state state :methods [[get [Object] Object] [put [Object Object] void] [clear [] void] [remove [Object] void] [isEmpty [] boolean] [size [] int]])) (defn -init [] [[] (atom {})]) (defn -clear [this] (reset! (.state this) {})) (defn -get [this k] (get @(.state this) k nil)) (defn -put [this k v] (swap! (.state this) assoc k v)) (defn -remove [this k] (swap! (.state this) dissoc k)) (defn -isEmpty [this] (zero? (count @(.state this (defn -size [this] (count @(.state this))) (defn -iterator [this] (.iterator @(.state this))) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: osx + clojure + emacs + leiningen blog posts
On Dec 28, 2:32 pm, gaz jones gareth.e.jo...@gmail.com wrote: i put together a couple of blog posts around how i use clojure + emacs + leiningen on OSX (but applies to linux too) in the hope it may help someone get up and running faster: Looks good. I should mention that installing the elisp for swank- clojure is actually no longer necessary. Also it's a little more convenient to use C-c C-k instead of C-c C-l to compile the current file. It might be nice to link to the Leiningen tutorial for further reference since it goes into more detail: https://github.com/technomancy/leiningen/blob/master/TUTORIAL.md very nice, Phil -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Speed of clojure hash map vs java hash map
On Tue, Dec 28, 2010 at 8:57 PM, Mark Engelberg mark.engelb...@gmail.comwrote: Just for fun, I was curious to see what it would be like, performance-wise, to simulate a synchronized mutable hash map by putting a clojure hash map inside an atom, and making this accessible to Java code via the map interface. ;; ~50ms-60ms (dotimes [_ 10] (let [m (atom {}) r (range 1e5)] (time (doseq [i r] (swap! m assoc i 2) ;; same as above (dotimes [_ 10] (let [m {} r (range 1e5)] (time (loop [m m r r] (if (nil? r) m (recur (assoc m (first r) 2) (next r))) (def ^java.util.Map j (. java.util.Collections synchronizedMap (java.util.HashMap.))) ;; ~10ms (dotimes [_ 10] (time (doseq [i (range 1e5)] (.put j i 2 So it's about 5X-6X slower for 1e5. But it looks to me there's no overhead from atom operations. I note that for 1e3 keys the difference is around 2X. Of course this isn't much of a comparison IMO because the Java HashMap isn't persistent. The Clojure version can add many keys as an atomic operation. Much more useful if you're using a map as some kind of in-memory data store. David -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Speed of clojure hash map vs java hash map
On Tue, Dec 28, 2010 at 6:46 PM, David Nolen dnolen.li...@gmail.com wrote: So it's about 5X-6X slower for 1e5. But it looks to me there's no overhead from atom operations. I got similar results (5x slower) on the same sorts of tests. Calling it from the class generated by genclass seemed to cause another 2x slowdown, resulting in the 10x difference I was seeing. It slows down more as you go to 10e6, which indicates that it's not just a constant factor slower than Java. I know that Clojure's data structures are actually log32n, but I'm so used to thinking of that as essentially constant that I was surprised to see such a noticeable difference in how much slower it was on 10e6 elements vs 10e5. I note that for 1e3 keys the difference is around 2X. Of course this isn't much of a comparison IMO because the Java HashMap isn't persistent. The Clojure version can add many keys as an atomic operation. Much more useful if you're using a map as some kind of in-memory data store. I ran this test because I was having a discussion with someone about the benefits of Clojure's persistent data structures, and how concurrency is handled by sticking an immutable data structure into an atom, ref, or agent, rather than through synchronized blocks. The discussion went in the direction of memory caches as an example of the two approaches. The discussion went like this. I said, So you get the benefit of no blocking on reading, you can even iterate over a snapshot of the hash table without blocking -- it's just a whole lot cleaner. That must be wildly inefficient. It's not as inefficient as you might think. [Insert discussion of log32, shared structure, etc.] But surely you're still paying a pretty high price. And why would you want that to be the default, paying that price all the time? Clearly, I couldn't really answer that question without doing some investigating to see what the speed difference is like. I was even hoping that if the speed difference were small enough, I could bundle up a little library that implements HashMap as a Clojure hash map in an atom, so that my Java pals could start using Clojure's hash maps as a drop-in replacement for Java's (that's where the gen-class piece of the experiment comes in). But with a 10x speed difference and so much more memory churn, I think that's going to be a tough sell. It's possible that Clojure becomes more competitive with Java under a lot of contention for access from different threads, but I haven't tested that out yet. Anyway, thanks for confirming that the ratio of speeds on your machine are similar to mine. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Question about when to use protocol+record and compilation warnings
Thanks everyone for all of the feedback. I think I have a solution to the warnings and if I understand deftype/defrecord, I should be able to replace defrecord with deftype in my implementation. I'll give it a try and report back when I have a chance. Thanks, Damon On Dec 26, 7:31 pm, David Nolen dnolen.li...@gmail.com wrote: On Sun, Dec 26, 2010 at 9:00 PM, Ken Wesson kwess...@gmail.com wrote: On Sun, Dec 26, 2010 at 9:25 PM, Alex Osborne a...@meshy.org wrote: Ken Wesson kwess...@gmail.com writes: Actually you don't need to AOT compile records or types. They work fine for interactive development. Eh. That's not what I saw written elsewhere. Or is it just protocols? Though usually those are used hand-in-hand with records. Perhaps you're thinking of gen-class? No. Protocols are also fine for interactive development. Someone here definitely said, recently and specifically, that at least one of the feature-complex around deftype/defprotocol/defrecord required AOT compilation. definterface/deftype/defprotocol/et al do not require AOT. structmaps are a legacy feature. defrecord is the way to go now. I've encountered some odd behavior at the SLIME REPL on occasion, but I haven't yet pinpointed a specific flow to recreate. It wasn't serious enough to impede interactive development. David -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Speed of clojure hash map vs java hash map
I thought it'd be interesting to look closer at the insertion times as a fx of the size of the Map. The results are at: https://gist.github.com/758198 At first I thought I'd found something interesting, only to investigate further and realize that I'd been testing through a fx that was using reflection (see trial results at bottom, Trials 1-4), and this was completely swamping the results. In Trial #5, I realized what I'd done, and broke my generic test fx into two separate functions w/ proper type hinting (my-test-map and my-test-nbhm). Now my results are on par w/ yours, and I don't see any significant change in insertion times as a fx of map size up to 1e5. Overall, NonBlockingHashMap insertions to take ~10x longer than the SynchronizedHashMap. I think your idea of measuring under heavy contention would be very useful. -Todd On 12/28/10 9:27 PM, Mark Engelberg wrote: On Tue, Dec 28, 2010 at 6:46 PM, David Nolendnolen.li...@gmail.com wrote: So it's about 5X-6X slower for 1e5. But it looks to me there's no overhead from atom operations. I got similar results (5x slower) on the same sorts of tests. Calling it from the class generated by genclass seemed to cause another 2x slowdown, resulting in the 10x difference I was seeing. It slows down more as you go to 10e6, which indicates that it's not just a constant factor slower than Java. I know that Clojure's data structures are actually log32n, but I'm so used to thinking of that as essentially constant that I was surprised to see such a noticeable difference in how much slower it was on 10e6 elements vs 10e5. I note that for 1e3 keys the difference is around 2X. Of course this isn't much of a comparison IMO because the Java HashMap isn't persistent. The Clojure version can add many keys as an atomic operation. Much more useful if you're using a map as some kind of in-memory data store. I ran this test because I was having a discussion with someone about the benefits of Clojure's persistent data structures, and how concurrency is handled by sticking an immutable data structure into an atom, ref, or agent, rather than through synchronized blocks. The discussion went in the direction of memory caches as an example of the two approaches. The discussion went like this. I said, So you get the benefit of no blocking on reading, you can even iterate over a snapshot of the hash table without blocking -- it's just a whole lot cleaner. That must be wildly inefficient. It's not as inefficient as you might think. [Insert discussion of log32, shared structure, etc.] But surely you're still paying a pretty high price. And why would you want that to be the default, paying that price all the time? Clearly, I couldn't really answer that question without doing some investigating to see what the speed difference is like. I was even hoping that if the speed difference were small enough, I could bundle up a little library that implements HashMap as a Clojure hash map in an atom, so that my Java pals could start using Clojure's hash maps as a drop-in replacement for Java's (that's where the gen-class piece of the experiment comes in). But with a 10x speed difference and so much more memory churn, I think that's going to be a tough sell. It's possible that Clojure becomes more competitive with Java under a lot of contention for access from different threads, but I haven't tested that out yet. Anyway, thanks for confirming that the ratio of speeds on your machine are similar to mine. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Speed of clojure hash map vs java hash map
On Wed, Dec 29, 2010 at 12:27 AM, Mark Engelberg mark.engelb...@gmail.comwrote: Clearly, I couldn't really answer that question without doing some investigating to see what the speed difference is like. I was even hoping that if the speed difference were small enough, I could bundle up a little library that implements HashMap as a Clojure hash map in an atom, so that my Java pals could start using Clojure's hash maps as a drop-in replacement for Java's (that's where the gen-class piece of the experiment comes in). But with a 10x speed difference and so much more memory churn, I think that's going to be a tough sell. It's possible that Clojure becomes more competitive with Java under a lot of contention for access from different threads, but I haven't tested that out yet. Anyway, thanks for confirming that the ratio of speeds on your machine are similar to mine. Even in in a single threaded context raw insert performance isn't the final word. What if you want to be able to deliver a snapshot for reporting? In Clojure that's free. In Java that's a blocking copy of a HashMap with 1e5 keys. Ick. That's the problem with naive benchmarks. They only sound good until you have to write real programs that do real work. David -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Speed of clojure hash map vs java hash map
On Tue, Dec 28, 2010 at 10:15 PM, David Nolen dnolen.li...@gmail.com wrote: Even in in a single threaded context raw insert performance isn't the final word. What if you want to be able to deliver a snapshot for reporting? What if you don't? Seriously, I agree with you that Clojure's data structures have some significant advantages -- if you need those advantages. There are still plenty of apps that use hash tables in a single-threaded manner, or use them in a multithreaded way where contention is unlikely and persistence is unnecessary. In many areas, Clojure has a pay-for-what-you-need philosophy -- this just isn't one of those areas. With respect to data structures, Clojure is very opinionated, with an attitude of Write it with immutable data structures -- you'll thank me later. :) Since all the existing Java structures are easy enough to access if you want them, this isn't necessarily a bad thing. It just means I have to rethink my proselytizing strategy -- I was definitely overselling the speed of the persistent data structures. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Question about when to use protocol+record and compilation warnings
This worked as expected. I just replaced defrecord with deftype here https://github.com/drsnyder/beanstalk/blob/82f301f1f825bb05aa14d85a220ec57c1dea61b2/src/beanstalk/core.clj#L117 and re-ran my tests. The suggestion from Baishampayan to add (:refer-clojure :exclude [read peek use]) also worked. I added this to the core.clj and the tests and there are no warnings. Thanks! Damon On Dec 28, 9:45 pm, Damon Snyder drsny...@gmail.com wrote: Thanks everyone for all of the feedback. I think I have a solution to the warnings and if I understand deftype/defrecord, I should be able to replace defrecord with deftype in my implementation. I'll give it a try and report back when I have a chance. Thanks, Damon On Dec 26, 7:31 pm, David Nolen dnolen.li...@gmail.com wrote: On Sun, Dec 26, 2010 at 9:00 PM, Ken Wesson kwess...@gmail.com wrote: On Sun, Dec 26, 2010 at 9:25 PM, Alex Osborne a...@meshy.org wrote: Ken Wesson kwess...@gmail.com writes: Actually you don't need to AOT compile records or types. They work fine for interactive development. Eh. That's not what I saw written elsewhere. Or is it just protocols? Though usually those are used hand-in-hand with records. Perhaps you're thinking of gen-class? No. Protocols are also fine for interactive development. Someone here definitely said, recently and specifically, that at least one of the feature-complex around deftype/defprotocol/defrecord required AOT compilation. definterface/deftype/defprotocol/et al do not require AOT. structmaps are a legacy feature. defrecord is the way to go now. I've encountered some odd behavior at the SLIME REPL on occasion, but I haven't yet pinpointed a specific flow to recreate. It wasn't serious enough to impede interactive development. David -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Speed of clojure hash map vs java hash map
On Dec 28, 10:28 pm, Mark Engelberg mark.engelb...@gmail.com wrote: On Tue, Dec 28, 2010 at 10:15 PM, David Nolen dnolen.li...@gmail.com wrote: Even in in a single threaded context raw insert performance isn't the final word. What if you want to be able to deliver a snapshot for reporting? What if you don't? Use transients? (dotimes [_ 10] (let [m (atom (transient {})) r (range 1e5)] (time (doseq [i r] (swap! m assoc! i 2) is within 50% the speed of an ordinary java.util.HashMap, by my measurements. And if you want snapshots at every step, in the worst case you pay the price you've measured above. -Jason -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en