Re: I don't understand this exception
Dear Meikel and Ken, Thank you very much for your corrections and suggestions! I admit it took a while for me to understand the more sophisticated parts of your code, but on the way I learned quite a lot about the correct usage of conj, assoc, update-in, and fnil! Best regards, Stefan On Jan 17, 3:21 pm, Ken Wesson kwess...@gmail.com wrote: On Mon, Jan 17, 2011 at 1:47 AM, Stefan Rohlfing stefan.rohlf...@gmail.com wrote: Hi all, I am trying to implement the function 'group-by' from Clojure.Core using my current knowledge of Clojure but cannot get pass a java.lang.Exception. This is the code so far: (defn key? [key coll] (some #{key} (keys coll))) (defn my-group-by [f coll] (let [test (fn [m x] (let [res (f x)] (if (key? res m) (conj (m res) x) (assoc m res (vec x)] (reduce test {} coll))) First of all, your key? is only ever (supposed to be) called on maps, so you can dispense with it: (defn my-group-by [f coll] (let [test (fn [m x] (let [res (f x)] (if (contains? res m) (conj (m res) x) (assoc m res (vec x)] (reduce test {} coll))) Second, your already-in-the-map case returns a vector. It doesn't modify the vector in place; it makes a new one with one more item and returns that. Not the map it should return. The next iteration of your reduce, the vector gets passed to key? with some value. Your key? function calls keys on it, which results in an exception. I get: user= (keys ['x 'y 'z]) java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to java.util.Map$Entry You got: ;; java.lang.Exception: Unable to convert: class java.lang.Integer to Object[] (repl-1:2) I'm not sure why the difference -- different Clojure versions? -- but no matter, the fix is the same: (defn my-group-by [f coll] (let [test (fn [m x] (let [res (f x)] (if (contains? res m) (assoc m res (conj (m res) x)) (assoc m res (vec x)] (reduce test {} coll))) This actually returns an updated map and not just an updated vector. But it can be made nicer in a couple of ways. One uses the optional not-found option to get to dispense with the contains?: (defn my-group-by [f coll] (let [test (fn [m x] (let [res (f x)] (assoc m res (conj (m res []) x] (reduce test {} coll))) And the other uses update-in. Update-in means the key only needs to be specified once, which lets you dispense with the inner let: (defn my-group-by [f coll] (let [test (fn [m x] (update-in m [(f x)] #(if % (conj % x) [x])))] (reduce test {} coll))) This can be formatted a bit more nicely: (defn my-group-by [f coll] (reduce (fn [m x] (update-in m [(f x)] #(if % (conj % x) [x]))) {} coll)) This gets rid of the outer let as well. The latter two versions can't distinguish the map having a key with an associated value of nil and the map lacking that key; however, the map never associates a key with anything other than a vector, so this ends up not mattering. For reference (and I only peeked at this *after* writing all of the above), the implementation of group-by in clojure.core is: (defn group-by Returns a map of the elements of coll keyed by the result of f on each element. The value at each key will be a vector of the corresponding elements, in the order they appeared in coll. {:added 1.2 :static true} [f coll] (persistent! (reduce (fn [ret x] (let [k (f x)] (assoc! ret k (conj (get ret k []) x (transient {}) coll))) This is basically the same as the version I got adding the optional not-found argument to get instead of using update-in, except that it uses transients for the performance benefits (and has docstrings and metadata) and gets rid of the outer let in the same manner as the final update-in using version I wrote. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: list* does not make a list?
The docs don't say that it is lazy. How (as a newbie) can i tell that it is lazy? Docs: Creates a new list containing the items prepended to the rest, the last of which will be treated as a sequence. On 17/01/11 06:27, Sean Allen wrote: the documentation on that could be improved. the doc string for that is basically the same as for list. but they return different types. rather surprising when you first see it. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: list* does not make a list?
Hi, On 17 Jan., 11:28, LordGeoffrey lordgeoff...@optusnet.com.au wrote: The docs don't say that it is lazy. How (as a newbie) can i tell that it is lazy? By the words the last of which will be treated as a sequence. A sequence is (in general) lazy. Hence, what list* returns is actually a sequence and not a list. As mentioned elsewhere the docs could be improved and the name list* was likely a suboptimal choice. Sincerely Meikel -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: Enhanced Primitive Support Syntax
On Mon, Jan 17, 2011 at 3:10 AM, chris cnuern...@gmail.com wrote: Is it insane to suggest that perhaps clojure should work with scala such that we can write both languages in the same file? A lot of reasons for which it is not possible: - it would mean coordinating two implementations/implementers. - it would prevent to go to platform for which there is no support in the other language. - A type checker would not be really happy to deal with a lot of Object - Object functions... - it would be ugly Having a bit of (optional) type inference for performance and compile-time safety in Clojure could be interesting though. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Typos in (doc add-watch)
On Sun, Jan 16, 2011 at 5:37 PM, Stuart Halloway stuart.hallo...@gmail.com wrote: The 'if' is terse, but correct: call is on agent's thread only when reference is an agent, and before pending sends only when reference is an agent or ref. Ah, it makes sense now. Thanks. I believe it'd be more comprehensible with your changes. Jacek -- Jacek Laskowski Java EE, functional languages and IBM WebSphere - http://blog.japila.pl -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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 Quizzes?
Taking a page out of the python book , I like to include a statement at the end that checks to see if the program is being run as a command-line program and then respond accordingly. As an example, (if (command-line?) (your-awesome-function (read-integer (first *command-line-args* Might appear at the end of my file. command-line? and read-integer are listed below (ns coderloop.utils (:use [clojure.contrib [duck-streams :only [file-str read-lines]]]) (:use [clojure [string :only [trim blank? split]]])) (defn read-integer [file] (Integer/parseInt (trim (slurp (file-str file) (defn command-line? [] (.isAbsolute (java.io.File. *file*))) This has the advantage of also working when the namespace is being run on the command-line with no arguments, but not when the namespace is being used or required by another namespace. read-integer is just a simple example for how to read a single integer from a file. You can then actually run your program by making a shell script with something like #!/bin/bash java -Xmn500M -Xms2000M -Xmx2000M -server -cp ./lib/*:./src clojure.main your-namespace-file.clj $@ A little known fact is that the above can actually be embedded into a clojure source file with the following trick: Make this the first line of your clojure namespace to make it executable: :;exec java -verbose:gc -Xmn500M -Xms2000M -Xmx2000M -server -cp your-classpath clojure.main $0 $*; The trick is putting the :; at the beginning and then calling exec. To clojure this looks like a literal string followed by a comment. To bash it looks like a no-op followed by an invocation of java on the file itself, and no lines after the first ever get executed. You can make whatever class structure you cant and then just symlink the clojure file to be an executable file at the base of the directory. You can still always go the shell script route if you don't like the embedding trick. This technique is common with emacs-lisp to make things executable. Hope that helps. sincerely, --Robert McIntyre On Sun, Jan 16, 2011 at 9:56 PM, Stuart Campbell stu...@harto.org wrote: On 17 January 2011 13:48, John Svazic jsva...@gmail.com wrote: Benny already answered, but here's the common block that I'm using for my Clojure submissions: (import '(java.io BufferedReader FileReader)) (defn process-file [file-name] (let [rdr (BufferedReader. (FileReader. file-name))] (line-seq rdr))) (defn my-func [col] ; Do something interesting ) (println (my-func (process-file (first *command-line-args* Basically I read the lines of the file into a sequence, then process that sequence in my function. Since I'm only dealing with the first parameter passed to my script, a (first *command-line-args*) call is equivalent to args[0] in other languages like Java. If you include clojure.contrib.io, you could use read-lines: (defn read-lines Like clojure.core/line-seq but opens f with reader. Automatically closes the reader AFTER YOU CONSUME THE ENTIRE SEQUENCE. [f] (let [read-line (fn this [^BufferedReader rdr] (lazy-seq (if-let [line (.readLine rdr)] (cons line (this rdr)) (.close rdr] (read-line (reader f Regards, Stuart -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group 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: check if something can be coerced to a seq
The problem with a seq-able? predicate is that the definition of what is seq-able is often context-dependent. `seq` works on Strings, but you probably don't want `flatten` to turn a String into a sequence of characters. -S clojure.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
HPC in scala ..
Hello Everybody, not directly related to clojure .. but it is interesting to know that scala people got a huge funding to further the state of the art in HPC... http://www.scala-lang.org/node/8579 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
Re: check if something can be coerced to a seq
2011/1/17 Stuart Sierra the.stuart.sie...@gmail.com The problem with a seq-able? predicate is that the definition of what is seq-able is often context-dependent. `seq` works on Strings, but you probably don't want `flatten` to turn a String into a sequence of characters. Good point. There is no static atom/listp distinction in Clojure. Still a predicate function for can yield a seq is missing, to provide a flexible flatten implementation like: (defn my-flatten ([pred coll] (mapcat (fn [p] (if (pred (first p)) (mapcat my-flatten p) p)) (partition-by pred coll))) ([coll] (my-flatten sequential? coll))) Jürgen -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Euler 14
Hi. I am using max-key to get the longest sequence from a couple of sequences. (defn cseq [n] (if (= 1 n) [1] (cons n (cseq (if (even? n) (/ n 2) (+ (* 3 n) 1 )) (apply max-key count (map cseq (range 1 100))) This gives me a heap error. To my understanding max-key should keep at most two sequences in memory. I could certainly solve this by working around the problem, but I want to understand where my logic fails. Thankful for any help. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Create a map from two seqs
Greetings, Apologies if this seems like a pointless question but a) searches were fruitless and b) hopefully this is interesting to consider ... I'm wanting to create a map from two seqs (:keys and values), and it seems surprisingly tricky. I would rather not use hash-map, but if I did the following would suffice: = (apply hash-map (apply concat (map vector [:a :b :c] [[1 2] [2 3] [3 4]]))) {:a [1 2], :c [3 4], :b [2 3]} The quick answer would be a function equivalent to {} in the place of hash-map above, but I can't find such a thing. My two answers are: a) compose assoc functions: = ((apply comp (map #(fn [m] (assoc m % %2)) [:a :b :c] [[1 2] [2 3] [3 4]])) nil) {:a [1 2], :b [2 3], :c [3 4]} b) recursion: = (loop [[k ks] [:a :b :c] [v vs] [[1 2] [2 3] [3 4]] m {}] (if (not k) m (recur ks vs (assoc m k v {:c [3 4], :b [2 3], :a [1 2]} Both seem wizzy/overly complex. I should probably just use hash- map ... but am I missing some elegant way to perform this with vanilla map? Thanks, Stuart -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: Create a map from two seqs
Hi Stuart, I believe you might looking for zipmap: - clojure.core/zipmap ([keys vals]) Returns a map with the keys mapped to the corresponding vals. This is used as follows: user= (zipmap [:a :b :c] [[1 2] [3 4] [5 6]]) {:c [5 6], :b [3 4], :a [1 2]} There are a lot of handy functions like this in core but you really need to know they exist before you can use them. Discovering new ones is always exciting! Sam --- http://sam.aaron.name On 17 Jan 2011, at 16:56, Stuart Popejoy wrote: Greetings, Apologies if this seems like a pointless question but a) searches were fruitless and b) hopefully this is interesting to consider ... I'm wanting to create a map from two seqs (:keys and values), and it seems surprisingly tricky. I would rather not use hash-map, but if I did the following would suffice: = (apply hash-map (apply concat (map vector [:a :b :c] [[1 2] [2 3] [3 4]]))) {:a [1 2], :c [3 4], :b [2 3]} The quick answer would be a function equivalent to {} in the place of hash-map above, but I can't find such a thing. My two answers are: a) compose assoc functions: = ((apply comp (map #(fn [m] (assoc m % %2)) [:a :b :c] [[1 2] [2 3] [3 4]])) nil) {:a [1 2], :b [2 3], :c [3 4]} b) recursion: = (loop [[k ks] [:a :b :c] [v vs] [[1 2] [2 3] [3 4]] m {}] (if (not k) m (recur ks vs (assoc m k v {:c [3 4], :b [2 3], :a [1 2]} Both seem wizzy/overly complex. I should probably just use hash- map ... but am I missing some elegant way to perform this with vanilla map? Thanks, Stuart -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group 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: Enhanced Primitive Support Syntax
Yeah yeah! http://www.google.com/search?q=lisp+type+inference Chris On Jan 17, 5:55 am, nicolas.o...@gmail.com nicolas.o...@gmail.com wrote: On Mon, Jan 17, 2011 at 3:10 AM, chris cnuern...@gmail.com wrote: Is it insane to suggest that perhaps clojure should work with scala such that we can write both languages in the same file? A lot of reasons for which it is not possible: - it would mean coordinating two implementations/implementers. - it would prevent to go to platform for which there is no support in the other language. - A type checker would not be really happy to deal with a lot of Object - Object functions... - it would be ugly Having a bit of (optional) type inference for performance and compile-time safety in Clojure could be interesting though. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Create a map from two seqs
On Mon, Jan 17, 2011 at 10:14, Sam Aaron samaa...@gmail.com wrote: There are a lot of handy functions like this in core but you really need to know they exist before you can use them. Discovering new ones is always exciting! I've found lurking in #clojure on irc to be a great way to find out about the functions in core. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Euler 14
Your cseq is not lazy, and some of the sequences can be quite long, so it wouldn't surprise me if that's the source of your problem. You can test if this is the problem by doing something like: (dorun (map cseq (range 1 100))) which removes the max-key from the computation entirely. You'll probably need to reformulate cseq with lazy lists. Even then, you will likely find that this program will be too slow without further optimizations (e.g., memoization or dynamic programming). That's the nature of project Euler problems; the obvious way to solve the problem is often too slow and further cleverness is required. On Mon, Jan 17, 2011 at 7:53 AM, Andreas Liljeqvist bon...@gmail.com wrote: Hi. I am using max-key to get the longest sequence from a couple of sequences. (defn cseq [n] (if (= 1 n) [1] (cons n (cseq (if (even? n) (/ n 2) (+ (* 3 n) 1 )) (apply max-key count (map cseq (range 1 100))) This gives me a heap error. To my understanding max-key should keep at most two sequences in memory. I could certainly solve this by working around the problem, but I want to understand where my logic fails. Thankful for any help. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group 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: Euler 14
I don't see why the cseq's have to be lazy, they are at the most 525 elements long. shouldn't each sequence only be produced when it is reduced in max-key and then discarded? But it makes a difference: (defn cseq [n] (if (= 1 n) [1] (lazy-seq (cons n (cseq (if (even? n) (/ n 2) (+ (* 3 n) 1 ))) (apply max-key count (map cseq (range 1 100))) gives me results. (def a (apply max-key count (map cseq (range 1 100 gives a heap error. Thanks for your answer. 2011/1/17 Mark Engelberg mark.engelb...@gmail.com Your cseq is not lazy, and some of the sequences can be quite long, so it wouldn't surprise me if that's the source of your problem. You can test if this is the problem by doing something like: (dorun (map cseq (range 1 100))) which removes the max-key from the computation entirely. You'll probably need to reformulate cseq with lazy lists. Even then, you will likely find that this program will be too slow without further optimizations (e.g., memoization or dynamic programming). That's the nature of project Euler problems; the obvious way to solve the problem is often too slow and further cleverness is required. On Mon, Jan 17, 2011 at 7:53 AM, Andreas Liljeqvist bon...@gmail.com wrote: Hi. I am using max-key to get the longest sequence from a couple of sequences. (defn cseq [n] (if (= 1 n) [1] (cons n (cseq (if (even? n) (/ n 2) (+ (* 3 n) 1 )) (apply max-key count (map cseq (range 1 100))) This gives me a heap error. To my understanding max-key should keep at most two sequences in memory. I could certainly solve this by working around the problem, but I want to understand where my logic fails. Thankful for any help. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.comclojure%2bunsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.comclojure%2bunsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: HPC in scala ..
Hello Everybody, not directly related to clojure .. but it is interesting to know that scala people got a huge funding to further the state of the art in HPC... http://www.scala-lang.org/node/8579 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 Very interesting. I wonder if Clojure can be one of the polymorphic targets. Certainly the Clojure macro facility can lift raw Clojure toward the DSL. Sigh. Yet more papers to read. :-) Tim Daly -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: Enhanced Primitive Support Syntax
Hi Stuart, On 2011-01-15, at 4:06 PM, Stuart Halloway wrote: In my experience, errors are the problem and we should be avoiding them, almost at all costs. This debate always starts by conflating three things into two, and then goes downhill from there. :-( It isn't (a) safe/slow vs. (b) unsafe/fast. That's how us outsiders are left to look at it. It is (a) unsafe/incorrect value on overflow/fastest/unifiable* vs. (b) safe/error on overflow/fast/unifiable vs. (c) safe/promoting on overflow/slow/not-unifiable *unifiable: able to deliver same semantics for primitives and objects This doesn't really help me understand your argument. It looks to me as though Clojure is trying to steer itself through the middle of something. The trouble is that I don't know where the edges of the middle are. Maybe it is just a documentation problem. But I'd also suggest that there's a bit of a sales job necessary here. We have thought about this quite a bit, Nobody doubts that, certainly I don't. And I'm not trying to minimise or dismiss what you've done. And I'm not claiming that I've thought about it better or more or deeper. But I do have concerns and I don't see them being addressed, and I'd like it if they weren't minimised either. Maybe my concerns are completely addressed. Maybe not. I don't know, and I'd like to be convinced. and an argument from one axis only (e.g safe/unsafe) that doesn't even mention some of the other axes is not likely to be persuasive. Would be more interesting to see a new axis we haven't thought of... Numerical correctness, for some of us, is an overwhelming issue. This is purely from experience... bad experience... 30+ years of bad experience in my case :-) From my point of view, the approach Clojure is taking isn't persuasive, not to say it couldn't be made persuasive. I think I did add what might be considered an additional axis. Syntax. Specifically what annotations are needed and for what purpose. I don't think this should be dismissed out of hand. Cheers, Bob Stu Stuart Halloway Clojure/core http://clojure.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 Bob Hutchison Recursive Design Inc. http://www.recursive.ca/ weblog: http://xampl.com/so -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
best way to define alias for all publics in ns?
I have this function which takes all of the publics from one ns and exports them in the current ns. My question is, is this the best way to do it? Is there another method which doesnt use eval? I know eval is supposed to be 'evil ' :) (defn ns-export [from-ns] (map (fn [[sym var]] (let [v (if (.hasRoot var) (var-get var)) var-obj (if v (intern *ns* sym v))] (when var-obj (alter-meta! var-obj (fn [old] (merge (meta var) old))) var-obj))) (ns-publics from-ns)) true) (defmacro eval-when [ args] (eval `(do ~@args)) nil) (eval-when (require 'clojure.contrib.error-kit) (ns-export (find-ns 'clojure.contrib.error-kit))) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: Enhanced Primitive Support Syntax
On Jan 16, 6:18 pm, Sean Corfield seancorfi...@gmail.com wrote: On Sun, Jan 16, 2011 at 3:50 PM, Jason Wolfe ja...@w01fe.com wrote: Moreover, we do not need to redefine the class at run-time. A simple way to do this: when you compile a function with arithmetic operations, concatenate bytecode for two versions: essentially, one with the unprimed (exception-throwing) ops and one with the primed (overflowing) ones. Now, replace the exceptions in the first path with local jumps into the second path. There are probably ways to get around generating two copies of the bytecode in advance, and making such a unilateral shift to inefficient semantics, but I don't know enough about JVM internals to say for sure. The problem is that if you have an arbitrary form that can operate entirely in primitives (some loop/recur perhaps) and you allow primitives to magically convert to Objects in that code, then the entire piece of code has to handle both primitives AND Objects and every single sub-form must be capable of handling primitives as input AND Objects as input and returning primitives if possible... You can't have automatic promotion to Object from primitive and expect any reasonable code to be generated that can maintain primitive performance across arbitrary expressions. Either everything can work with Objects - and you lose performance - or everything must be able to work within primitives (and at most throw exceptions) and remain performant. I think you can. Let me elaborate on my simplistic example. Compile the code for a function twice -- once where everything works within primitives, and once where everything works with Objects -- and concatenate the bytecode together. Start by running the primitive version. On overflow, jump into the corresponding spot in the object version (after some patching up / boxing) -- rather than throwing an exception. If no overflow happens, you run *exactly* the same bytecode as the current unprimed ops. (I'm not sure how this would interact with JIT compared to exceptions, though). As soon as overflow happens, you run code as if all of the operations were primed, until function call exit. I believe this is related to the approach used by TraceMonkey, Firefox's Javascript compiler: http://hacks.mozilla.org/2009/07/tracemonkey-overview/ Anyway, I'll leave this be now; I just wanted to mention the idea since I hadn't seen it discussed. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: Enhanced Primitive Support Syntax
On Mon, Jan 17, 2011 at 1:05 PM, Bob Hutchison hutch-li...@recursive.ca wrote: Numerical correctness, for some of us, is an overwhelming issue. This is purely from experience... bad experience... 30+ years of bad experience in my case :-) From my point of view, the approach Clojure is taking isn't persuasive, not to say it couldn't be made persuasive. Under the current proposal, you should never get an incorrect answer. You might get an error, though. It's a subtle difference, but this is the main reason why the developers don't see it as a correctness issue. If your program runs, and gives you back an answer, it will be correct. If it crashes, you convert to the overflow version of arithmetic, or typecast some of your numbers to bigints, and you'll get the right answer. I think a lot of the argument from both sides boils down to how much you fear runtime crashes. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: Euler 14
On Mon, Jan 17, 2011 at 11:55 AM, Andreas Liljeqvist bon...@gmail.com wrote: I don't see why the cseq's have to be lazy, they are at the most 525 elements long. shouldn't each sequence only be produced when it is reduced in max-key and then discarded? You're right, the chains aren't as long as I thought. I can't think of any good explanation as to why max-key blows the heap when cseq is non-lazy and doesn't when cseq is lazy. (I confirmed that on my system, I get the same behavior as you, even set to a 1600MB heap size). Interestingly, this: (apply max (map count (map cseq (range 1 100 works just fine with non-lazy seq. The only real difference between this and the max-key version is that reducing the max-key requires keeping around the longest list so far, whereas this one just keeps around the count. But keeping around a 525 element list shouldn't be enough to overflow the heap. I've tried to figure out: Could max-key be holding on to the heads of these lists? Could this be an effect of chunked sequences? The chunked sequences explanation seems almost plausible. You could in theory have 32 lists realized at once, plus the biggest one you've seen so far. But even in the worst-case scenario, you're talking about 15000 elements, and I don't see how that could overflow the heap. Just out of curiosity, I tried this with an unchunked range, and still got the heap overflow, so I don't see how it could be a chunking issue. Furthermore if either of these were the problem, you'd expect to see the same problem with lazy cseq, because ultimately count has to realize the lazy cseq, so if too many heads were being retained at once, the lazy version would exhibit the same heap space problem. This leads to the more disturbing possibility that maybe there's a garbage collection flaw relating to non-lazy lists. I'd love to see some more people investigate this and see if we can come up with a good explanation as to why the original poster's code overflows the heap space. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: best way to define alias for all publics in ns?
woops, mistake (defn ns-export [from-ns] (count (doall (map (fn [[sym var]] (let [v (if (.hasRoot var) (var-get var)) var-obj (if v (intern *ns* sym v))] (when var-obj (alter-meta! var-obj (fn [old] (merge (meta var) old))) var-obj))) (ns-publics from-ns) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: best way to define alias for all publics in ns?
Taking the risk to be ridiculous in the front of all my peers : how is your function different from the clojure.core/use function, exactly ? 2011/1/17 Seth wbu...@gmail.com woops, mistake (defn ns-export [from-ns] (count (doall (map (fn [[sym var]] (let [v (if (.hasRoot var) (var-get var)) var-obj (if v (intern *ns* sym v))] (when var-obj (alter-meta! var-obj (fn [old] (merge (meta var) old))) var-obj))) (ns-publics from-ns) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.comclojure%2bunsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: best way to define alias for all publics in ns?
Hi Laurent, Am 17.01.2011 um 22:32 schrieb Laurent PETIT: Taking the risk to be ridiculous in the front of all my peers : how is your function different from the clojure.core/use function, exactly ? It's more like immigrate from earlier compojure versions. When you use this namespace it will also provide the functions from from-ns. This is not the case with use. This has of course subtle implications when used eg. with binding. immigrate was deprecated from compojure, IIRC. Sincerely Meikel -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: Enhanced Primitive Support Syntax
On Jan 17, 3:17 pm, Jason Wolfe ja...@w01fe.com wrote: I think you can. Let me elaborate on my simplistic example. Compile the code for a function twice -- once where everything works within primitives, and once where everything works with Objects -- and concatenate the bytecode together. Start by running the primitive version. On overflow, jump into the corresponding spot in the object version (after some patching up / boxing) -- rather than throwing an exception. If no overflow happens, you run *exactly* the same bytecode as the current unprimed ops. (I'm not sure how this would interact with JIT compared to exceptions, though). As soon as overflow happens, you run code as if all of the operations were primed, until function call exit. I'm not sure the JVM allows methods to do that; it might be possible though. This doesn't address the issue that a method has to decide up front whether it is going to return a primitive or an object. I suppose you could compile two versions of each function, but brings up two issues: First, there would be massive code bloat, which might hurt the ability of the code to be JITed well. Second, if a function is hinted to return a primitive, it would almost certainly be an error to return something that isn't a primitive. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Clojure/JVM languages internal presentation
Hey guys, This past summer I gave a presentation on JVM langauges at our company's worldwide developer summit. I tried to get approval for Clojure but had to settle for Scala because its syntax didn't frighten management. I figured I'd share it in case any of the slides can be of use elsewhere. open in browser (no notes): http://public.iwork.com/document/?d=JVM_Languages.keya=p1045023190 src: https://github.com/rcampbell/jvm-languages The talk (w/notes in github .key file) was very important and the slides don't make much sense without it, but it generally went like: -Topic is JVM languages, what they are, why we should care about them -We (as a mostly Java house) have two big problems: bloat and concurrency -Show bloat with examples, try to illustrate a trend -Why are these other languages so concise? -Go back over the examples pulling out a single language feature from each (in bold), explain how it leads to more concise code -Talk a bit about concurrency, No free lunch (R), Ghz wall, cores increasing -Java's answer to concurrency is difficult to work with -Make a token effort to select a JVM language based on books, perceived momentum/maturity/community, etc -Select Clojure and Scala, end with Scala example since that's the one that was approved (replace slide here :-) Rob -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Enhanced Primitive Support Syntax
On Jan 17, 3:24 pm, Brian Goslinga quickbasicg...@gmail.com wrote: On Jan 17, 3:17 pm, Jason Wolfe ja...@w01fe.com wrote: I think you can. Let me elaborate on my simplistic example. Compile the code for a function twice -- once where everything works within primitives, and once where everything works with Objects -- and concatenate the bytecode together. Start by running the primitive version. On overflow, jump into the corresponding spot in the object version (after some patching up / boxing) -- rather than throwing an exception. If no overflow happens, you run *exactly* the same bytecode as the current unprimed ops. (I'm not sure how this would interact with JIT compared to exceptions, though). As soon as overflow happens, you run code as if all of the operations were primed, until function call exit. I'm not sure the JVM allows methods to do that; it might be possible though. I believe it's possible, as long as the bytecodes are combined into a single method body (due to the local jump restriction). This doesn't address the issue that a method has to decide up front whether it is going to return a primitive or an object. I suppose you could compile two versions of each function, but brings up two issues: First, there would be massive code bloat, which might hurt the ability of the code to be JITed well. This is an issue. I believe it might be avoidable with some tricks, but I don't know enough about JVM internals to say for sure. (I can elaborate on ideas if requested). Second, if a function is hinted to return a primitive, it would almost certainly be an error to return something that isn't a primitive. Correct. As I mentioned earlier, if you hint the return as long, we would always return a long (truncating/throwing if necessary). This is only talking about behavior *within* a function; the external interface of the function is not up for interpretation. And, taking a step back, what people seem to be concerned with is long semantics being inferred when that's not what they want. If the user explicitly declares the return value to be a long, this concern would no longer apply. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: Enhanced Primitive Support Syntax
I'll also add that type inference wouldn't solve the problem, it would just move the pain the the design of the type system and details relating to it. The type system would probably be at least as complex as Java generics to be something worthwhile if you do the type inferencing for perf primarily and type checking incidentally; if you want type checking primarily it would most likely be even more complicated. The changes in 1.3 don't really make the language more complicated; in contrast, type inferencing would. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Book on Ring - reviewers needed
I'm working on a short book on Ring for the Pragmatic Bookshelf. The first two chapters are here: http://exampler.com/tmp/ring.pdf If you'd like to be a reviewer, send me mail. - Brian Marick, Artisanal Labrador Contract programming in Ruby and Clojure Author of /Ring/ (forthcoming; sample: http://exampler.com/tmp/ring.pdf) www.exampler.com, www.exampler.com/blog, www.twitter.com/marick -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: best way to define alias for all publics in ns?
if you 'use' ns A in ns B, ns C which uses B will not see the functions of A. Im trying to create a ns which collects functions from various other ns and exports them so that all you have to do is use that one uber ns. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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: best way to define alias for all publics in ns?
On Mon, Jan 17, 2011 at 10:47 PM, Seth wbu...@gmail.com wrote: if you 'use' ns A in ns B, ns C which uses B will not see the functions of A. Im trying to create a ns which collects functions from various other ns and exports them so that all you have to do is use that one uber ns. And, Clojure being a language with good meta facilities, you figured it ought to be as easy as (ns uber-ns :use (other-ns yet-another-ns)) (foo other-ns) (foo yet-another-ns) for some choice of foo. I'd figure something like this might work: (defn make-def [name value] `(def name value)) (defmacro foo [target-ns] `(do ~@(map #(make-def % (symbol (str target-ns / %))) (get-all-public-symbols target-ns given an implementation of get-all-public-symbols that, given a namespace *symbol* and *at macroexpansion time*, produces a seq of the symbols of public vars in that namespace; so if called on the symbol 'clojure.core it would produce something like ('condp 'for 'map 'doall 'println 'seq ...) and foo would produce something like (do (def condp clojure.core/condp) (def for clojure.core/for) ...). Making foo copy the metadata of the var as well as the value is left as an exercise for the reader. As is implementing get-all-public-symbols. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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 Quizzes?
On Jan 17, 7:42 am, Robert McIntyre r...@mit.edu wrote: You can then actually run your program by making a shell script with something like #!/bin/bash java -Xmn500M -Xms2000M -Xmx2000M -server -cp ./lib/*:./src clojure.main your-namespace-file.clj $@ A little known fact is that the above can actually be embedded into a clojure source file with the following trick: Make this the first line of your clojure namespace to make it executable: :;exec java -verbose:gc -Xmn500M -Xms2000M -Xmx2000M -server -cp your-classpath clojure.main $0 $*; The trick is putting the :; at the beginning and then calling exec. To clojure this looks like a literal string followed by a comment. To bash it looks like a no-op followed by an invocation of java on the file itself, and no lines after the first ever get executed. You can make whatever class structure you cant and then just symlink the clojure file to be an executable file at the base of the directory. You can still always go the shell script route if you don't like the embedding trick. This technique is common with emacs-lisp to make things executable. Instead of a trick, why not use the fact that clojure treats #! as a single-line comment? Then you can write your shebang line just like every other scripting language. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Testing if a sequence is lazy
Hi, I'm wondering if there is a good way to test if a given sequence is lazy, and if so, how much of it has been evaluated. I know the fact that it is lazy should be transparent, but I'm thinking in the context of unit testing knowing that could be valuable. For instance if you know a particular sequence could be particularly large or expensive in certain situations, you may want your tests to assert that it is not getting evaluated prematurely. I suppose I could hack the generator function to cause a side effect that I could test for, but is there an easier way? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from 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 Quizzes?
Because there is a limit on the length of the shebang line to as short as 80 characters in some distributions (notably ubuntu), and the posix standard for the shebang line does not allow you to pass any arguments to the interperter to modify its behaviour --- so no classpath or anything else for you! Try it --- you'll see that the standard shebang line just doesn't work for most project setups. Embedding shell gets around all these problems. sincerely, --Robert McIntyre On Tue, Jan 18, 2011 at 12:03 AM, Alan a...@malloys.org wrote: On Jan 17, 7:42 am, Robert McIntyre r...@mit.edu wrote: You can then actually run your program by making a shell script with something like #!/bin/bash java -Xmn500M -Xms2000M -Xmx2000M -server -cp ./lib/*:./src clojure.main your-namespace-file.clj $@ A little known fact is that the above can actually be embedded into a clojure source file with the following trick: Make this the first line of your clojure namespace to make it executable: :;exec java -verbose:gc -Xmn500M -Xms2000M -Xmx2000M -server -cp your-classpath clojure.main $0 $*; The trick is putting the :; at the beginning and then calling exec. To clojure this looks like a literal string followed by a comment. To bash it looks like a no-op followed by an invocation of java on the file itself, and no lines after the first ever get executed. You can make whatever class structure you cant and then just symlink the clojure file to be an executable file at the base of the directory. You can still always go the shell script route if you don't like the embedding trick. This technique is common with emacs-lisp to make things executable. Instead of a trick, why not use the fact that clojure treats #! as a single-line comment? Then you can write your shebang line just like every other scripting language. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group 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: HPC in scala ..
Hello Everybody, not directly related to clojure .. but it is interesting to know that scala people got a huge funding to further the state of the art in HPC... http://www.scala-lang.org/node/8579 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 I have just finished Language Virtualization for Heterogeneous Parallel Computing http://infoscience.epfl.ch/record/148814/files/paper.pdf The fundamental idea is defining a DSL (domain specific language) to express some ideas. The DSL lives in a layer above the implementation language but is embedded into the implementation language. That is, the DSL does not have a separate compiler. DSLs define languages that can support this as virtualization languages (VL). The VL needs to provide four properties: 1) expressiveness -- everything should be expressible in the VL 2) performance -- the DSL should perform at VL speeds 3) safety -- the DSL should not reach into the underlying VL 4) effort -- the DSL should be easy to implement. DSLs should be easy to combine because they both rest on the same VL. Thus, a developer can provide capabilities of multiple DSLs in the same image. Clojure clearly fulfills all of the goals of a virtualization language because it is a Lisp. Lisp systems are clearly capable of building a DSL that is fully expressive of all of the power of Lisp. By using the macro facility the DSL syntax can be matched to the problem domain. Macros allow the Clojure code to dynamically generate high performance code that takes advantage of domain specific optimizations. The macro language can be defined independent of the underlying lisp so that there is no need to reach below the VL into Clojure. This gives the DSL portability. Macros are minimal effort. It is easy to develop macros and easy to incrementally develop and enhance them to support any DSL features. So I think that Clojure is an excellent virtualization language for DSLs. While I do not know of any large Clojure applications yet, I know that Axiom can be viewed as a mathematical domain specific language in Common Lisp with facilities similar to Mathematica. ACL2 is a logical domain specific language in Common Lisp with the ability to prove lisp programs. Because they have a common VL they can be combined into the same lisp image and ACL2 can be used to prove Axiom mathematical statements. Lisp systems like Clojure make this combination simple to implement. I believe that, given enough time for Clojure to mature, we will see large domain specific languages developed. These will be easy to combine in a single Clojure image. This paper provides a potential way to write parallel code for specific domains. It attracted multi-million euro funding and could represent a specific way forward for parallel Clojure programs. Tim Daly -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en