Re: Binding values in a list of symbols and evaluating as code
Hi, Am 25.01.2009 um 08:41 schrieb Greg Harman: This could be a real problem for Clojure. I can think of other techniques that could easily result in the creation a large number of anonymous functions that ought to get gc'd after a few ms but permanently increase memory usage by a significant amount. I don't know the JVM very well at all. Are there any ways around this? Are techniques that generate a lot of short-lived functions just not practical in Clojure? It seems that anonymous functions in general might be a sort of anti- pattern. Beyond deeply-nested applications like GP, there's the case of any long-running process e.g. pretty much any server application. The growth might be slower, but sooner or later that server is going to accumulate too many... Disclaimer: Every information of the Clojure internals in the following are impressions I got from reading the list. So they might be true or they might not be true. Every function in Clojure creates a class. So if one encounters a (fn [a b] (+ a b)) at runtime, there is simply a new class instance created, which is then .invoked with values for a and b. So the number of "functions" is known at compile time. Note: macros happen at compile-time, so functions generated by a macro are also known at compile-time. At runtime there is simply an instance which gets gc'd. So saying "anonymous functions in general might be a sort of anti-pattern" is equal to saying "Vectors in general might be sort of anti-pattern", because there is nothing different happening. I didn't follow the thread in much detail, but that is what I have left in my memory: What might be an anti-pattern is using eval. Ok ok. I know eval has its uses, but using eval with fn might be an anti-pattern. From my point of view, the following is happening: One calls (eval '(fn )). Each and every call to eval creates a new class. Even for identical fn's. So what cloggs the memory are not the function instances themselves. They get gc'd. But the generated classes stay in memory. They don't go away. This is what brings down the system finally. (eval '(fn ..)) should not be a thing you should find in a "long running server application". Maybe only in form of debug repl. But generating enough fn classes in that repl to bring down the server Does this make sense? Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: Binding values in a list of symbols and evaluating as code
How about compiling a closure tree ? ;; very basic example follows (defn make+ [param1 param2] (fn [environement] (+ (param1 environement) (param2 environement (defn make* [param1 param2] (fn [environement] (* (param1 environement) (param2 environement (defn make-variable [variable-name] (fn [environement] (environement variable-name))) (defn make-number [number] (fn [environement] number)) (def *mappings* {'+ make+ '* make*}) (defn my-compile [expression] (cond (seq? expression) ((*mappings* (first expression)) (my-compile (nth expression 1)) (my-compile (nth expression 2))) (number? expression) (make-number expression) (symbol? expression) (make-variable expression))) (defn test-it [] (let [compiled (my-compile '(+ (* a 2) (+ b a)))] (map compiled (list {'a 0 'b 0} {'a 1 'b 2} {'a 2 'b 1} {'a 4 'b 5} cara.data.expressions=> (time (dotimes [a 100] (test-it))) "Elapsed time: 3160.461437 msecs" That's for 1 million compilations and 4 times as many executions. There's no problem with garbage collection. I beleive this "compiler pattern" is pretty common. Sacha --~--~-~--~~~---~--~~ 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 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: Binding values in a list of symbols and evaluating as code
Phlex wrote: > How about compiling a closure tree ? > > ;; very basic example follows > > (defn make+ [param1 param2] > (fn [environement] > (+ (param1 environement) (param2 environement > > (defn make* [param1 param2] > (fn [environement] > (* (param1 environement) (param2 environement > > (defn make-variable [variable-name] > (fn [environement] > (environement variable-name))) > > (defn make-number [number] > (fn [environement] > number)) > > (def *mappings* {'+ make+ > '* make*}) > > (defn my-compile [expression] > (cond >(seq? expression) ((*mappings* (first expression)) > (my-compile (nth expression 1)) > (my-compile (nth expression 2))) >(number? expression) (make-number expression) >(symbol? expression) (make-variable expression))) > > (defn test-it [] > (let [compiled (my-compile '(+ (* a 2) (+ b a)))] > (map compiled (list {'a 0 'b 0} > {'a 1 'b 2} > {'a 2 'b 1} > {'a 4 'b 5} > > cara.data.expressions=> (time (dotimes [a 100] (test-it))) > "Elapsed time: 3160.461437 msecs" > > The test should of course be cara.data.expressions=> (time (dotimes [a 100] (doall (test-it "Elapsed time: 5436.411073 msecs" without the doall, the lazy sequence does not get evaluated ! Sacha --~--~-~--~~~---~--~~ 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 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: Binding values in a list of symbols and evaluating as code
Zak Wilson a écrit : > Thanks, Christophe. It works now, and it's fast. > > Unfortunately, now I've run in to Nathan's problem. After a few > thousand generations, resulting in the creation of about half a > million functions it was using over a gig of memory and died with an > OutOfMemoryError. > I don't > know the JVM very well at all. Are there any ways around this? Are > techniques that generate a lot of short-lived functions just not > practical in Clojure? > Yes there are a way around this: permgen memory is released when the classloader is GCed so, if you use a transient classloader, your anonymous functions can be collected. I need to refresh my knowledge of Clojure internals. Christophe --~--~-~--~~~---~--~~ 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 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: PermGen growth
Clojure creates class not for every function call, but for every function definition. The PermGen growth you see is the REPL compiling your input, most likely. On Sun, Jan 25, 2009 at 8:26 AM, Greg Harman wrote: > > I'm trying to debug a problem in one of my programs in which PermGen > usage grows with and during each run (cumulatively within the same > REPL session) until I eventually run out & get the out of memory JVM > exception. So I wrote the following utility just to help me track > usage while I hack: > > (defn permGen > [] > (let [beans (java.lang.management.ManagementFactory/ > getMemoryPoolMXBeans)] >(doseq [mx beans] > (when (= "Perm Gen" (.getName mx)) >(println (.getUsage mx)) > > I ran this several times in succession: > > gp=> (permGen) > # committed = 16777216(16384K) max = 67108864(65536K)> > nil > gp=> (permGen) > # committed = 16777216(16384K) max = 67108864(65536K)> > nil > gp=> (permGen) > # committed = 16777216(16384K) max = 67108864(65536K)> > nil > gp=> (permGen) > # committed = 16777216(16384K) max = 67108864(65536K)> > > The thing to notice is that the used PermGen has grown by 1-2K with > each run (I ran it many more times than I pasted, and that growth rate > seems pretty steady). What I don't understand is why. If I understand > PermGen correctly, it holds class definitions. In Clojure classes are > only generated with calls to fn (see > http://groups.google.com/group/clojure/browse_thread/thread/2c66650b9057f760/11a09103da821264?lnk=gst&q=permgen#11a09103da821264), > and I don't have any sort of nested function creation inside my > (permGen) function. > > I don't have any anonymous function definitions in my function, so > what is causing the used PermGen growth? > > thanks, > Greg > > > -- Venlig hilsen / Kind regards, Christian Vest Hansen. --~--~-~--~~~---~--~~ 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 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: Binding values in a list of symbols and evaluating as code
On Sun, Jan 25, 2009 at 11:13 AM, Christophe Grand wrote: > Zak Wilson a écrit : >> know the JVM very well at all. Are there any ways around this? Are >> techniques that generate a lot of short-lived functions just not >> practical in Clojure? >> > Yes there are a way around this: permgen memory is released when the > classloader is GCed so, if you use a transient classloader, your > anonymous functions can be collected. There's just this caveat; All Objects have a reference to their Class, and all Classes have a reference to their ClassLoader, which in turn have references to all Classes that it has loaded. So, if an Object whose Class was loaded by loader A holds a reference to any Object whose Class was loaded by loader B, then you will not be able to GC loader B or any of its classes. -- Venlig hilsen / Kind regards, Christian Vest Hansen. --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
definline example?
Hi all, I'd like to repeat my request for an example of definline usage; I feel I've tried everything. user=> (definline f [x] x) java.lang.ExceptionInInitializerError (NO_SOURCE_FILE:1) user=> (definline [x] x) java.lang.NullPointerException (NO_SOURCE_FILE:2) user=> (definline (f [x] x)) java.lang.NullPointerException (NO_SOURCE_FILE:3) user=> (definline (defmacro f [x] x)) java.lang.NullPointerException (NO_SOURCE_FILE:4) user=> (definline f) java.lang.NullPointerException (NO_SOURCE_FILE:12) Thanks, Anand --~--~-~--~~~---~--~~ 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 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: definline example?
Hi Anand, Here is an example from core.clj: (definline doubles "Casts to double[]" [xs] `(. clojure.lang.Numbers doubles ~xs)) As you can see it is using macro magic as you would expect for in- lining. Regards, Tim. On Jan 25, 11:06 pm, Anand Patil wrote: > Hi all, > > I'd like to repeat my request for an example of definline usage; I > feel I've tried everything. > > user=> (definline f [x] x) > java.lang.ExceptionInInitializerError (NO_SOURCE_FILE:1) > user=> (definline [x] x) > java.lang.NullPointerException (NO_SOURCE_FILE:2) > user=> (definline (f [x] x)) > java.lang.NullPointerException (NO_SOURCE_FILE:3) > user=> (definline (defmacro f [x] x)) > java.lang.NullPointerException (NO_SOURCE_FILE:4) > user=> (definline f) > java.lang.NullPointerException (NO_SOURCE_FILE:12) > > Thanks, > Anand --~--~-~--~~~---~--~~ 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 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: definline example?
On Sun, Jan 25, 2009 at 7:06 AM, Anand Patil wrote: > > I'd like to repeat my request for an example of definline usage; I > feel I've tried everything. I looked into this yesterday, and it seems to me that definline has been broken since SVN rev 1065. I don't know why the usages of it in core.clj don't cause errors at compile time, but they don't seem to work quite right. When used as a function, they work fine: user=> (apply ints [(into-array Integer/TYPE [1 2 3])]) # But when used as a macro, they return nil: user=> (ints (into-array Integer/TYPE [1 2 3])) nil --Chouser --~--~-~--~~~---~--~~ 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 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: Agent as a processing queue
On Jan 23, 10:43 pm, e wrote: > Just to understand ... 'send-future' works too but you don't think that's > the way to go? The Agent send pool has a limited size, so doing recursive calls with a stack greater than that size will result in a freeze (waiting for new threads that can't be made yet). So send-future can't be used with my naive example only send-off-future. However being a naive example it is also very inefficient, a real implementation would be more careful in dividing up the work, and in doing so would remove this recursive requirement. I was mainly exploring the differences between futures and agents, and it seemed to me that futures were convenient in cases like this (one shot computations). > Also, I need to see if the Java code has a place for a user > to specify the thread pool size. Otherwise is that best handled by > send-off-future wrapping a generator that can throttle or something? http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Executors.html (.. Runtime getRuntime availableProcessors) You could divide the input into nprocessors subsets and run them as futures using a normal pquicksort, and combine the results and return them. This is a similar strategy to pmap in core.clj, which uses agents. Regards, Tim. --~--~-~--~~~---~--~~ 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 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: Binding values in a list of symbols and evaluating as code
On Jan 25, 2009, at 5:13 AM, Christophe Grand wrote: > > Zak Wilson a écrit : >> Thanks, Christophe. It works now, and it's fast. >> >> Unfortunately, now I've run in to Nathan's problem. After a few >> thousand generations, resulting in the creation of about half a >> million functions it was using over a gig of memory and died with an >> OutOfMemoryError. >> I don't >> know the JVM very well at all. Are there any ways around this? Are >> techniques that generate a lot of short-lived functions just not >> practical in Clojure? >> > Yes there are a way around this: permgen memory is released when the > classloader is GCed so, if you use a transient classloader, your > anonymous functions can be collected. > I've made it so eval uses an ephemeral classloader in all cases (svn 1232). Rich (defn perm-gen [] (let [beans (java.lang.management.ManagementFactory/ getMemoryPoolMXBeans)] (doseq [mx beans] (when (= "Perm Gen" (.getName mx)) (println (.getUsage mx)) (let [fdef `(fn [x#] x#)] (dotimes [_ 10] (dotimes [_ 1000] (eval fdef)) (perm-gen))) # # # # # # # # # # --~--~-~--~~~---~--~~ 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 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: PermGen growth
I believe you, but I don't understand why. I'm doing nothing but evaluate my test function over and over. Since no new functions are being defined, why would this evaluation use any PermGen? On Jan 25, 5:57 am, Christian Vest Hansen wrote: > Clojure creates class not for every function call, but for every > function definition. > > The PermGen growth you see is the REPL compiling your input, most likely. --~--~-~--~~~---~--~~ 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 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: PermGen growth
When the reader has a top-level expression in the REPL, it gets evaluated. Evaluation goes through the Compiler which generates bytecode from your forms. Before the bytecode can be executed, it needs to be loaded into the JVM, and that happens by wrapping it in a class and loading that. On Sun, Jan 25, 2009 at 3:08 PM, Greg Harman wrote: > > I believe you, but I don't understand why. I'm doing nothing but > evaluate my test function over and over. Since no new functions are > being defined, why would this evaluation use any PermGen? > > On Jan 25, 5:57 am, Christian Vest Hansen > wrote: >> Clojure creates class not for every function call, but for every >> function definition. >> >> The PermGen growth you see is the REPL compiling your input, most likely. > > > > -- Venlig hilsen / Kind regards, Christian Vest Hansen. --~--~-~--~~~---~--~~ 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 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: PermGen growth
To clarify: On Sun, Jan 25, 2009 at 3:08 PM, Greg Harman wrote: > > I believe you, but I don't understand why. I'm doing nothing but > evaluate my test function over and over. Exactly. This input is evaluated and compiled over and over. > Since no new functions are > being defined, The expression to call your function was being defined over and over, causing new classes to be generated. This is a side-effect of eval, which the REPL is based upon. > why would this evaluation use any PermGen? > > On Jan 25, 5:57 am, Christian Vest Hansen > wrote: >> Clojure creates class not for every function call, but for every >> function definition. >> >> The PermGen growth you see is the REPL compiling your input, most likely. > > > > -- Venlig hilsen / Kind regards, Christian Vest Hansen. --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Support for disabling forms (reader macro similar to CL's #-(and))
I couldn't find anything in Clojure that would correspond to Common Lisp's reader conditionals, in particular the extremely useful #-(and) idiom. I would like to suggest the inclusion of a reader macro: #* or something of the kind, that would simply ignore the form right after it. That would allow for easy out-commenting of entire forms. The reader macro should preferably be very short and easy to type, as it gets used quite often. I initially thought about #!, but that seems to have been taken for unix shell scripting support. --J. --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
zipper: missing root-loc
I tried using the zipper data structure and immediately noticed, that there is a function I need, which isn't there. I would like to have something like root-loc (with a better name), that would do exactly what root does, except it would return a tree location, not just the root node. Or perhaps root should return a location, and root-node should return the node? The reason for this is simple: I walk and "modify" my tree in a number of ways, and then I want to zip things up to the root and pass the entire tree to another function. From what I understand, currently the only way is to get the root node and then recreate the entire zipper structure. This seems unnecessary. Am I missing something, or is that a worthwile addition? --J. --~--~-~--~~~---~--~~ 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 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: Binding values in a list of symbols and evaluating as code
Thanks for the explanation, Meikel. My statement about anti-pattern was predicated on each call to fn[] creating a new class - I see from your explanation and from going back and re-reading Rich's old posts on this topic that I misunderstood it before. (If it did create a new class each time, I'd hold my stance on it being an anti-pattern...) However, in practical use I've found that in a deeply nested application similar to the OP's genetic programming system that removing inline function definitions in favor of explicitly defining them as top-level named functions provides a significant boost in speed and reducation in PermGen usage. I must be missing something simple, but I can't figure out why PermGen would be affected if no classes are created. I think this line of discussion might actually merge with another thread I started yesterday: http://groups.google.com/group/clojure/browse_thread/thread/67f9d2df248d3aa0 (thought they were related but I didn't want to hijack this thread...) -Greg On Jan 25, 3:38 am, Meikel Brandmeyer wrote: > > Every function in Clojure creates a class. So if one encounters a > (fn [a b] (+ a b)) at runtime, there is simply a new class instance > created, which is then .invoked with values for a and b. So the > number of "functions" is known at compile time. Note: macros > happen at compile-time, so functions generated by a macro are > also known at compile-time. At runtime there is simply an instance > which gets gc'd. > > So saying "anonymous functions in general might be a sort of > anti-pattern" is equal to saying "Vectors in general might be sort > of anti-pattern", because there is nothing different happening. > > I didn't follow the thread in much detail, but that is what I have > left in my memory: > > What might be an anti-pattern is using eval. Ok ok. I know eval > has its uses, but using eval with fn might be an anti-pattern. > From my point of view, the following is happening: > One calls (eval '(fn )). Each and every call to eval creates > a new class. Even for identical fn's. So what cloggs the memory > are not the function instances themselves. They get gc'd. But > the generated classes stay in memory. They don't go away. > This is what brings down the system finally. > > (eval '(fn ..)) should not be a thing you should find in a "long > running server application". Maybe only in form of debug repl. > But generating enough fn classes in that repl to bring down the > server > > Does this make sense? > > Sincerely > Meikel > > smime.p7s > 5KViewDownload --~--~-~--~~~---~--~~ 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 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: PermGen growth
I see, so running (permGen) 10 times from the REPL is not the same as, say, (dotimes [_ 10] (permGen)), because there's an understood (eval) around anything executed directly in the REPL. Thanks. On Jan 25, 9:33 am, Christian Vest Hansen wrote: > When the reader has a top-level expression in the REPL, it gets > evaluated. Evaluation goes through the Compiler which generates > bytecode from your forms. Before the bytecode can be executed, it > needs to be loaded into the JVM, and that happens by wrapping it in a > class and loading that. > > On Sun, Jan 25, 2009 at 3:08 PM, Greg Harman wrote: > > > I believe you, but I don't understand why. I'm doing nothing but > > evaluate my test function over and over. Since no new functions are > > being defined, why would this evaluation use any PermGen? > > > On Jan 25, 5:57 am, Christian Vest Hansen > > wrote: > >> Clojure creates class not for every function call, but for every > >> function definition. > > >> The PermGen growth you see is the REPL compiling your input, most likely. > > -- > Venlig hilsen / Kind regards, > Christian Vest Hansen. --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
time lies, even with doall
The IRC channel folks helped me implement what we discovered was already called "separate" in contribs. My point was to do a partition that generated the two lists "(passes pred)" and "(fails pred)" in one pass without recursion. We ended up with: (defn filt-rem [pred coll] (loop [l1 () l2 () [f & r] coll] (if f (if (pred f) (recur (conj l1 f) l2 r) (recur l1 (conj l2 f) r)) (list l1 l2 -- the name reaming "filter and remove", I was thinking There's some branching there, so perhaps it's not the most efficient code. Here's what's in contrib, and as Tim showed me in the pquicksort discussion, that last bit could be replaced by "remove": (defn separate "Returns a vector: [ (filter f s), (filter (complement f) s) ]" [f s] [(filter f s) (filter (complement f) s)]) Well, the recursive one that does two passes blows away filt-rem, according to 'time'. But if I just count in my head, they both take about as long. Yes, I started throwing doall all over the place. The other thing is we definately aren't talking about milliseconds. I.m not trying to measure how much time is spent in the reader or compiler or whatever. I care about the user waiting for the answer, and that's what I'm trying to time. Here's what I'm seeing, even though I don't believe it: (def l1 (doall (take 5 (repeatedly #(rand-int 3000) ;;; I don't know if doall goes there, just shotgunning it at this point (time (filt-rem #(< % 1500) (doall l1))) I've tried doall in various places with no help "Elapsed time: 63.158 msecs"<-- no way. It took like 12 seconds (time (separate #(< % 1500) (doall l1))) ;; doall here actually did something even though already done above "Elapsed time: 12.701 msecs"<--- no way. 12 seconds, I counted. Definitely longer than 12 msecs. Questions: 1) Is there anything wrong with filt-rem or anything to improve it? 2) why are the times reportedly so different when I can tell they return in about the same amount of time? Thanks. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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: Binding values in a list of symbols and evaluating as code
I think using eval is generally considered an antipattern. It's generally slow, and it's easy to make confusing code with it. Phlex - thanks for the suggestion. I may give that a try. Rich - thanks for the fix. I'm trying it now. It looks like it's not experiencing any permanent growth, though it does grow pretty big temporarily. --~--~-~--~~~---~--~~ 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 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: time lies, even with doall
Hi e, I'm still learning the basics, very much like you( I guess you are ahead of me in Clojure). However, I have a question for you and not an answer to your questions. Why do you have doall here (def l1 (doall (take 5 (repeatedly #(rand-int 3000) . From my little knowledge of Clojure, take 5 would cause 'repeatedly' to be limited to 5 times and (repeatedly #(rand-int 3000) is an argument of take , so (take 5 (repeatedly #(rand-int 3000) given same results as your (doall (take 5 (repeatedly #(rand-int 3000 and by adding doall you are just increasing 'noise', that's my 2 cents. Doall , do, dorun are used in calling multiple functions(I hope am like :)), like (do (doo noot) (move "niger delta")) . Emeka --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Stream utilities in clojure.contrib
For those who like me are playing with the stream-enabled branch of Clojure, there is a new module stream-utils on clojure.contrib: http://code.google.com/p/clojure-contrib/source/browse/trunk/src/ clojure/contrib/stream-utils.clj Obviously this is very experimental, and absolutely not ready for use in applications. The module defines a couple of stream transformers and tools for writing stream transformers. Any feedback is welcome! As a result of writing this code, I have one modification request for Clojure's stream support: it would be very convenient if iters were callable, such that one could write (iter eos) instead of (next! iter eos). This would make it possible to use iters directly as an argument to stream. Motivation: a stream transformer involves the steps: stream -> iter -> (transformation) -> generator -> (transformation) - > stream Here "transformation" stands for a function that takes an iter/ generator and returns a new object of the same kind. There are two possible places in this chain to insert a transformation function, either at the iter level or at the generator level. I decided to implement transformations at the generator level, but one could as well do it at the iterator level. But in both cases, there is an addition step iterator->generator that is required only because iterators and generators have different calling interfaces, although they have pretty much the same behaviour. Konrad. --~--~-~--~~~---~--~~ 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 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: Support for disabling forms (reader macro similar to CL's #-(and))
Clojure has that in the comment form: (comment (do (not (eval 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 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: Support for disabling forms (reader macro similar to CL's #-(and))
Hi, Am 25.01.2009 um 17:11 schrieb Zak Wilson: Clojure has that in the comment form: (comment (do (not (eval this No. That's not equivalent. comment leaves a nil behind, while #* would not. [:a (comment :b) :c] => [:a nil :c] [:a #* :b :c] => [:a :c] Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
scoping clojure.contrib.shell-out to a directory?
I would like to convert the following ruby/rake code to Clojure: Dir.chdir ENV["CLOJURE_HOME"] do system "git svn rebase" system "ant jar" end Since Java does not have the notion of a current directory, one way to go about this would be to modify clojure.contrib.shell-out/sh as follows: (1) add a var *current-dir* (2) modify sh to use *current-dir* if it is set (3) create a macro to swap the binding for *current-dir* Chouser, would it be ok for me to make this change? What would you suggest the macro be named? with-dir? chdir? I would also welcome other approaches from folks who have been doing command-line stuff in Clojure. Cheers, 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 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: definline example?
On Sun, Jan 25, 2009 at 8:01 AM, Chouser wrote: > On Sun, Jan 25, 2009 at 7:06 AM, Anand Patil > wrote: >> >> I'd like to repeat my request for an example of definline usage; I >> feel I've tried everything. > > I looked into this yesterday, and it seems to me that definline has > been broken since SVN rev 1065. I don't know why the usages of it in > core.clj don't cause errors at compile time, but they don't seem to > work quite right. I wrote a new definline that seems to work correctly: (defmacro definline "Experimental - like defmacro, except defines a named function whose body is the expansion, calls to which may be expanded inline as if it were a macro. Cannot be used with variadic (&) args." [name & decl] (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] `(do (defn ~name ~...@pre-args ~args ~(apply (eval (list `fn args expr)) args)) (alter-meta! (var ~name) assoc :inline (fn ~args ~expr)) (var ~name Using definline work, and return the Var, just like defn does: user=> (definline inc2 "returns x plus 2" [x] `(+ 2 ~x)) #'user/inc2 The defined function works as a function: user=> (map inc2 [1 2 3]) (3 4 5) It also works inlined: user=> (inc2 5) 7 And even the docstring works, which I think it didn't before: user=> (doc inc2) - user/inc2 ([x]) returns x plus 2 nil This means that 'ints', 'doubles', and friends now work too: user=> (doubles (into-array Double/TYPE [1 2 3])) # user=> (doc doubles) - clojure.core/doubles ([xs]) Casts to double[] nil Patch attached. --Chouser --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~--- commit 407a65779f0ebc07772fded00e95225ccb7c8423 Author: Chouser Date: Sun Jan 25 12:13:59 2009 -0500 Fix definline diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 5c01215..8d3eef2 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -3031,14 +3031,13 @@ (defmacro definline "Experimental - like defmacro, except defines a named function whose body is the expansion, calls to which may be expanded inline as if - it were a macro. Cannot be used with variadic (&) args." + it were a macro. Cannot be used with variadic (&) args." [name & decl] - (let [[args expr] (drop-while (comp not vector?) decl) -inline (eval (list `fn args expr))] + (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] `(do - (defn ~name ~args ~(apply inline args)) - (let [v# (var ~name)] - (.setMeta v# (assoc ^v# :inline ~inline)) + (defn ~name ~...@pre-args ~args ~(apply (eval (list `fn args expr)) args)) + (alter-meta! (var ~name) assoc :inline (fn ~args ~expr)) + (var ~name (defn empty "Returns an empty collection of the same category as coll, or nil"
what's the typical usage of fn constantly
What's the typical usage of fn constantly ? thanks -sun --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
slime connect problems
I have embedded clojure-swank in my program like so: (defn ui-start-swank-server "Start a swank server. I think this prints out a port number but I am not certain" [logger-ref] (with-bindings (let [fname (.getCanonicalPath (fs-get-temp-file "swank"))] (start-server fname) (log-message @logger-ref "ui" :info "Started swank server: " (slurp fname) When trying to connect using slime-connect to the printed port number, I get (in the messages): Connecting to Swank on port 49534.. [2 times] Versions differ: 2009-01-23 (slime) vs. nil (swank). Continue? (y or n) error in process filter: ad-Orig-error: No inferior lisp process error in process filter: No inferior lisp process Emacs is still connected but I get no slime repl. Is everything working and is there a command that starts the slime repl? I am using the latest from CVS. Chris --~--~-~--~~~---~--~~ 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 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: scoping clojure.contrib.shell-out to a directory?
On Sun, Jan 25, 2009 at 11:52 AM, Stuart Halloway wrote: > > I would like to convert the following ruby/rake code to Clojure: > > Dir.chdir ENV["CLOJURE_HOME"] do > system "git svn rebase" > system "ant jar" > end > > Since Java does not have the notion of a current directory, one way to > go about this would be to modify clojure.contrib.shell-out/sh as > follows: > > (1) add a var *current-dir* > > (2) modify sh to use *current-dir* if it is set > > (3) create a macro to swap the binding for *current-dir* Yep, sounds good. Since Runtime.exec() already has an overload that takes a "working directory" arg, it seems quite sensible to expose this. It might also be nice to add another keyword option to 'sh' for this, for cases were you only have one command to execute in the given directory. Thous would work like the :out, :in, and :bytes options already supported. > Chouser, would it be ok for me to make this change? What would you > suggest the macro be named? with-dir? chdir? Please do! :-) In naming both the Var and the macro, it may be worth some effort to avoid implying to new users that you're actually changing Java's current working directory. Relative paths given to File and FileReader, for example, within a with-dir block will still not pick up the new value. So, perhaps *sh-dir*, with-sh-dir, and :dir? The acronym "cwd" is used in lots of other contexts for this, but may not be very easy to find. Perhaps that's not a problem, or on the other hand maybe it's not a common acronym in the Java world? --Chouser --~--~-~--~~~---~--~~ 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 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: Ratio conversions to BigDecimal and floating point values.
On Sat, Jan 24, 2009 at 2:41 PM, Jeremy Bondeson wrote: > > I have uploaded a second diff [1] that has these simplifications. Thanks for tracking this down. However, your patch cannot be accepted until Rich has gotten your CA: http://clojure.org/contributing Also, I believe he prefers patches be attached to the email message rather than uploaded to the files area. Thanks, --Chouser --~--~-~--~~~---~--~~ 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 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: definline example?
On Jan 25, 5:27 pm, Chouser wrote: > On Sun, Jan 25, 2009 at 8:01 AM, Chouser wrote: > > On Sun, Jan 25, 2009 at 7:06 AM, Anand Patil > > wrote: > > >> I'd like to repeat my request for an example of definline usage; I > >> feel I've tried everything. > > > I looked into this yesterday, and it seems to me that definline has > > been broken since SVN rev 1065. I don't know why the usages of it in > > core.clj don't cause errors at compile time, but they don't seem to > > work quite right. > > I wrote a new definline that seems to work correctly: > > (defmacro definline > "Experimental - like defmacro, except defines a named function whose > body is the expansion, calls to which may be expanded inline as if > it were a macro. Cannot be used with variadic (&) args." > [name & decl] > (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] > `(do > (defn ~name ~...@pre-args ~args ~(apply (eval (list `fn args expr)) > args)) > (alter-meta! (var ~name) assoc :inline (fn ~args ~expr)) > (var ~name > > Using definline work, and return the Var, just like defn does: > user=> (definline inc2 "returns x plus 2" [x] `(+ 2 ~x)) > #'user/inc2 > Terrific, thanks very much! Anand --~--~-~--~~~---~--~~ 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 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: slime connect problems
I figured out that I can run the command 'slime-repl' and get a valid repl. So the code I posted is all that is required to allow emacs to connect to your running process. Amazingly short. Chris On Jan 25, 10:35 am, chris wrote: > I have embedded clojure-swank in my program like so: > > (defn ui-start-swank-server > "Start a swank server. I think this prints out > a port number but I am not certain" > [logger-ref] > (with-bindings > (let [fname (.getCanonicalPath (fs-get-temp-file "swank"))] > (start-server fname) > (log-message @logger-ref "ui" :info "Started swank server: > " (slurp fname) > > When trying to connect using slime-connect to the printed port number, > I get (in the messages): > > Connecting to Swank on port 49534.. [2 times] > Versions differ: 2009-01-23 (slime) vs. nil (swank). Continue? (y or > n) > error in process filter: ad-Orig-error: No inferior lisp process > error in process filter: No inferior lisp process > > Emacs is still connected but I get no slime repl. Is everything > working and is there a command that starts the slime repl? I am using > the latest from CVS. > > Chris --~--~-~--~~~---~--~~ 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 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: Support for disabling forms (reader macro similar to CL's #-(and))
Meikel Brandmeyer writes: > Am 25.01.2009 um 17:11 schrieb Zak Wilson: > >> Clojure has that in the comment form: (comment (do (not (eval this > > No. That's not equivalent. comment leaves a nil behind, while #* > would not. > > [:a (comment :b) :c] => [:a nil :c] > [:a #* :b :c] => [:a :c] Exactly. In CL you can use #-(and) for anything, for example function arguments. I use it like that way regularly while developing code. It has to be a reader macro. --J. --~--~-~--~~~---~--~~ 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 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: time lies, even with doall
people are paying a lot of attention to "pure" functional languages, which I think mean ones that don't ever destroy data structures out from under people pointing at them. Instead, people who need different views just get their own different views -- possibly reusing common components. This other thing called "lazy" seems to mean that you don't need to do any work until someone asks for the results. . . .and then you do the minimum amount of work that's being asked for. I've heard of a Unix analogy: if you do a grep of just the first 5 times some pattern occurs, the whole pipeline can shut down after those 5 are found. The leading 'grep' needn't actually keep scanning the file (incidentally, I'm not sure that works right on windows/DOS pipes, where a copy of the whole file is sent across the pipe before even finding out what's being asked for). I'm hoping that "doall" gets rid of the laziness folks take a lot of pride in . . . .and makes it work like DOS. Otherwise, the timing won't really work. I'm asking with this question whether the contrib version is still being lazy and returning to (time) without doing much . . . and if so, how can I force it to actually do the work? On Sun, Jan 25, 2009 at 11:04 AM, Emeka wrote: > Hi e, > > I'm still learning the basics, very much like you( I guess you are ahead of > me in Clojure). However, I have a question for you and not an answer to your > questions. Why do you have doall here (def l1 (doall (take 5 > (repeatedly #(rand-int 3000) . From my little knowledge of Clojure, take > 5 would cause 'repeatedly' to be limited to 5 times and (repeatedly > #(rand-int 3000) is an argument of take , so (take 5 (repeatedly > #(rand-int 3000) given same results as your (doall (take 5 > (repeatedly #(rand-int 3000 and by adding doall you are just increasing > 'noise', that's my 2 cents. > Doall , do, dorun are used in calling multiple functions(I hope am like > :)), like (do (doo noot) (move "niger delta")) . > > Emeka > > > > > > > --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
is there a replace-at function
I ran into a situation where I needed to replace an element in a collection at a specific position, I ended up writing the following: (defn replace-at [coll pos value] "replaces an element in collection at pos with the value" (let [parts (split-at pos coll)] (concat (first parts) (cons value (rest (second parts)) I was wondering if there's a standard function to do 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 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: what's the typical usage of fn constantly
On Jan 25, 5:34 pm, wubbie wrote: > What's the typical usage of fn constantly ? When you need a function that constantly returns the same result :) That probably doesn't tell you any more than you know already, so I'll give you a real world use. My rnd-utils library has a function generating random strings that match a regular expression. It does this by converting a regex into a sequence of functions, and then concatenating the results into a string. So a regex like "ab[def]" would be converted into two functions: [(constantly "ab") (rnd-choice "def")] This can then be turned into a string using: (apply str (map apply function-sequence)) - James --~--~-~--~~~---~--~~ 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 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: time lies, even with doall
oh, so anyway, i put it in that specific place because I wasn't sure if, without it, l1 would just be some sort of smart, lazy list that only exists when you start trying to get the values. I didn't think so, but, again, I'm just trying to shotgun the problem. On Sun, Jan 25, 2009 at 1:57 PM, e wrote: > people are paying a lot of attention to "pure" functional languages, which > I think mean ones that don't ever destroy data structures out from under > people pointing at them. Instead, people who need different views just get > their own different views -- possibly reusing common components. > > This other thing called "lazy" seems to mean that you don't need to do any > work until someone asks for the results. . . .and then you do the minimum > amount of work that's being asked for. I've heard of a Unix analogy: if you > do a grep of just the first 5 times some pattern occurs, the whole pipeline > can shut down after those 5 are found. The leading 'grep' needn't actually > keep scanning the file (incidentally, I'm not sure that works right on > windows/DOS pipes, where a copy of the whole file is sent across the pipe > before even finding out what's being asked for). > > I'm hoping that "doall" gets rid of the laziness folks take a lot of pride > in . . . .and makes it work like DOS. Otherwise, the timing won't really > work. I'm asking with this question whether the contrib version is still > being lazy and returning to (time) without doing much . . . and if so, how > can I force it to actually do the work? > > > On Sun, Jan 25, 2009 at 11:04 AM, Emeka wrote: > >> Hi e, >> >> I'm still learning the basics, very much like you( I guess you are ahead >> of me in Clojure). However, I have a question for you and not an answer to >> your questions. Why do you have doall here (def l1 (doall (take 5 >> (repeatedly #(rand-int 3000) . From my little knowledge of Clojure, take >> 5 would cause 'repeatedly' to be limited to 5 times and (repeatedly >> #(rand-int 3000) is an argument of take , so (take 5 (repeatedly >> #(rand-int 3000) given same results as your (doall (take 5 >> (repeatedly #(rand-int 3000 and by adding doall you are just increasing >> 'noise', that's my 2 cents. >> Doall , do, dorun are used in calling multiple functions(I hope am like >> :)), like (do (doo noot) (move "niger delta")) . >> >> Emeka >> >> >> >> >> >> >> > --~--~-~--~~~---~--~~ 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 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: what's the typical usage of fn constantly
thanks James, I'll have a look. -sun On Jan 25, 2:00 pm, James Reeves wrote: > On Jan 25, 5:34 pm, wubbie wrote: > > > What's the typical usage of fn constantly ? > > When you need a function that constantly returns the same result :) > > That probably doesn't tell you any more than you know already, so I'll > give you a real world use. My rnd-utils library has a function > generating random strings that match a regular expression. It does > this by converting a regex into a sequence of functions, and then > concatenating the results into a string. > > So a regex like "ab[def]" would be converted into two functions: > [(constantly "ab") (rnd-choice "def")] > > This can then be turned into a string using: (apply str (map apply > function-sequence)) > > - James --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
zip/down bug?
I think zip/down has a bug. It effectively does (when (children loc) ...), and since in Clojure empty list isn't false, it ends up adding nodes in my tree. Shouldn't it check for (when-not (empty? (children loc)) ...) ? --J. --~--~-~--~~~---~--~~ 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 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: Ratio conversions to BigDecimal and floating point values.
On Jan 25, 2009, at 12:49 PM, Chouser wrote: Also, I believe he prefers patches be attached to the email message rather than uploaded to the files area. Here's the latest I have seen from Rich on the topic of where to put patches: http://groups.google.com/group/clojure/msg/e4dfeed57620f55e : For now I'd like to stick with first vetting bugs either here on the group, or if you catch me on the #clojure IRC. Patches should always be attached to issues. Thanks, Rich --Steve smime.p7s Description: S/MIME cryptographic signature
Re: is there a replace-at function
Hi, Am 25.01.2009 um 20:00 schrieb Dmitri: I ran into a situation where I needed to replace an element in a collection at a specific position, I ended up writing the following: (defn replace-at [coll pos value] "replaces an element in collection at pos with the value" (let [parts (split-at pos coll)] (concat (first parts) (cons value (rest (second parts)) I was wondering if there's a standard function to do this At least for vectors (and of course maps) you can use assoc-in. 1:1 user=> (assoc-in [1 2 3] [1] :x) [1 :x 3] Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: definline example?
On Jan 25, 12:27 pm, Chouser wrote: > On Sun, Jan 25, 2009 at 8:01 AM, Chouser wrote: > > On Sun, Jan 25, 2009 at 7:06 AM, Anand Patil > > wrote: > > >> I'd like to repeat my request for an example of definline usage; I > >> feel I've tried everything. > > > I looked into this yesterday, and it seems to me that definline has > > been broken since SVN rev 1065. I don't know why the usages of it in > > core.clj don't cause errors at compile time, but they don't seem to > > work quite right. > > I wrote a new definline that seems to work correctly: > > (defmacro definline > "Experimental - like defmacro, except defines a named function whose > body is the expansion, calls to which may be expanded inline as if > it were a macro. Cannot be used with variadic (&) args." > [name & decl] > (let [[pre-args [args expr]] (split-with (comp not vector?) decl)] > `(do >(defn ~name ~...@pre-args ~args ~(apply (eval (list `fn args expr)) > args)) >(alter-meta! (var ~name) assoc :inline (fn ~args ~expr)) >(var ~name > > Using definline work, and return the Var, just like defn does: > user=> (definline inc2 "returns x plus 2" [x] `(+ 2 ~x)) > #'user/inc2 > > The defined function works as a function: > user=> (map inc2 [1 2 3]) > (3 4 5) > > It also works inlined: > user=> (inc2 5) > 7 > > And even the docstring works, which I think it didn't before: > user=> (doc inc2) > - > user/inc2 > ([x]) > returns x plus 2 > nil > > This means that 'ints', 'doubles', and friends now work too: > > user=> (doubles (into-array Double/TYPE [1 2 3])) > # > > user=> (doc doubles) > - > clojure.core/doubles > ([xs]) > Casts to double[] > nil > > Patch attached. > --Chouser Patch applied, svn 1233 - thanks! Rich --~--~-~--~~~---~--~~ 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 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: Support for disabling forms (reader macro similar to CL's #-(and))
On Jan 25, 1:43 pm, Jan Rychter wrote: > Meikel Brandmeyer writes: > > Am 25.01.2009 um 17:11 schrieb Zak Wilson: > > >> Clojure has that in the comment form: (comment (do (not (eval this > > > No. That's not equivalent. comment leaves a nil behind, while #* > > would not. > > > [:a (comment :b) :c] => [:a nil :c] > > [:a #* :b :c] => [:a :c] > > Exactly. In CL you can use #-(and) for anything, for example function > arguments. I use it like that way regularly while developing code. It > has to be a reader macro. > I'm not ready to add a features-like system to Clojure just yet, but am in favor of a single-form comment-out reader macro. Just need to pick a dispatch character: #- #/ #; other candidates? Rich --~--~-~--~~~---~--~~ 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 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: is there a replace-at function
On Jan 25, 2:29 pm, Meikel Brandmeyer wrote: > Hi, > > Am 25.01.2009 um 20:00 schrieb Dmitri: > > > I ran into a situation where I needed to replace an element in a > > collection at a specific position, I ended up writing the following: > > > (defn replace-at [coll pos value] > > "replaces an element in collection at pos with the value" > > (let [parts (split-at pos coll)] > >(concat (first parts) (cons value (rest (second parts)) > > > I was wondering if there's a standard function to do this > > At least for vectors (and of course maps) you can use assoc-in. > > 1:1 user=> (assoc-in [1 2 3] [1] :x) > [1 :x 3] > Or simply assoc: (assoc [1 2 3] 1 :x) [1 :x 3] Rich --~--~-~--~~~---~--~~ 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 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: Support for disabling forms (reader macro similar to CL's #-(and))
On Sun, Jan 25, 2009 at 1:43 PM, Rich Hickey wrote: > > On Jan 25, 1:43 pm, Jan Rychter wrote: >> Meikel Brandmeyer writes: >> > Am 25.01.2009 um 17:11 schrieb Zak Wilson: >> >> >> Clojure has that in the comment form: (comment (do (not (eval this >> >> > No. That's not equivalent. comment leaves a nil behind, while #* >> > would not. >> >> > [:a (comment :b) :c] => [:a nil :c] >> > [:a #* :b :c] => [:a :c] >> >> Exactly. In CL you can use #-(and) for anything, for example function >> arguments. I use it like that way regularly while developing code. It >> has to be a reader macro. >> > > I'm not ready to add a features-like system to Clojure just yet, but > am in favor of a single-form comment-out reader macro. > > Just need to pick a dispatch character: > > #- > #/ > #; > > other candidates? I prefer #; since ; is already the normal comment character. -- R. Mark Volkmann Object Computing, Inc. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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 -~--~~~~--~~--~--~---
changes to test_clojure and test_contrib
In SVN 412 I have made the following changes to contrib: * a test_contrib.clj file which does for contrib what test_clojure.clj does for clojure * a test_clojure task in build.xml * a test_contrib task in build.xml * a test task to aggregate all test tasks This is *very* minimal, but I wanted it so I could TDD some other changes I am making to contrib. Feedback or further improvement most welcome. Let's write some tests! 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 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: Stream utilities in clojure.contrib
On Jan 25, 11:10 am, Konrad Hinsen wrote: > For those who like me are playing with the stream-enabled branch of > Clojure, there is a new module stream-utils on clojure.contrib: > >http://code.google.com/p/clojure-contrib/source/browse/trunk/src/ > clojure/contrib/stream-utils.clj > > Obviously this is very experimental, and absolutely not ready for use > in applications. The module defines a couple of stream transformers > and tools for writing stream transformers. Any feedback is welcome! > > As a result of writing this code, I have one modification request for > Clojure's stream support: it would be very convenient if iters were > callable, such that one could write (iter eos) instead of (next! iter > eos). This would make it possible to use iters directly as an > argument to stream. > > Motivation: a stream transformer involves the steps: > > stream -> iter -> (transformation) -> generator -> (transformation) - > > stream > > Here "transformation" stands for a function that takes an iter/ > generator and returns a new object of the same kind. There are two > possible places in this chain to insert a transformation function, > either at the iter level or at the generator level. I decided to > implement transformations at the generator level, but one could as > well do it at the iterator level. But in both cases, there is an > addition step iterator->generator that is required only because > iterators and generators have different calling interfaces, although > they have pretty much the same behaviour. > Looks interesting. I made AStream.Iter an IFn, so you can try that. One thing I would say is that, e.g. drop-first is eager - it drops the items from the source stream on creation. Streams will let us write things like drop fully lazily, and that should be the norm. Rich --~--~-~--~~~---~--~~ 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 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: time lies, even with doall
Hi e, Most of the time is taken up by printing, which is why you see the same times. Here's an example that gives the results you would expect. user> (def numbers (doall (take 50 (repeatedly #(rand-int 3000) #'user/numbers user> (defn predicate [x] (< x 1500)) #'user/predicate user> (dotimes [i 5] (time (do (filt-rem predicate numbers) nil))) "Elapsed time: 1028.112 msecs" "Elapsed time: 715.832 msecs" "Elapsed time: 923.726 msecs" "Elapsed time: 631.364 msecs" "Elapsed time: 934.084 msecs" nil user> (dotimes [i 5] (time (let [pair (separate predicate numbers)] (dorun (first pair)) (dorun (second pair) "Elapsed time: 2694.912 msecs" "Elapsed time: 2818.482 msecs" "Elapsed time: 3087.375 msecs" "Elapsed time: 2992.607 msecs" "Elapsed time: 2959.005 msecs" nil -Stuart Sierra On Jan 25, 10:02 am, e wrote: > The IRC channel folks helped me implement what we discovered was > already called "separate" in contribs. My point was to do a partition > that generated the two lists "(passes pred)" and "(fails pred)" in one > pass without recursion. > > We ended up with: > > (defn filt-rem [pred coll] > (loop [l1 () l2 () [f & r] coll] > (if f > (if (pred f) > (recur (conj l1 f) l2 r) > (recur l1 (conj l2 f) r)) > (list l1 l2 > > -- the name reaming "filter and remove", I was thinking > > There's some branching there, so perhaps it's not the most efficient > code. > > Here's what's in contrib, and as Tim showed me in the pquicksort > discussion, that last bit could be replaced by "remove": > > (defn separate > "Returns a vector: > [ (filter f s), (filter (complement f) s) ]" > [f s] > [(filter f s) (filter (complement f) s)]) > > Well, the recursive one that does two passes blows away filt-rem, > according to 'time'. But if I just count in my head, they both take > about as long. > > Yes, I started throwing doall all over the place. The other thing is > we definately aren't talking about milliseconds. I.m not trying to > measure how much time is spent in the reader or compiler or whatever. > I care about the user waiting for the answer, and that's what I'm > trying to time. > > Here's what I'm seeing, even though I don't believe it: > > (def l1 (doall (take 5 (repeatedly #(rand-int 3000) ;;; I > don't know if doall goes there, just shotgunning it at this point > > (time (filt-rem #(< % 1500) (doall l1))) I've tried doall in > various places with no help > "Elapsed time: 63.158 msecs" <-- no way. It took like 12 > seconds > > (time (separate #(< % 1500) (doall l1))) ;; doall here > actually did something even though already done above > "Elapsed time: 12.701 msecs" <--- no way. 12 seconds, I > counted. Definitely longer than 12 msecs. > > Questions: > > 1) Is there anything wrong with filt-rem or anything to improve it? > 2) why are the times reportedly so different when I can tell they > return in about the same amount of time? > > Thanks. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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: zipper: missing root-loc
On Sun, Jan 25, 2009 at 9:46 AM, Jan Rychter wrote: > > From what I understand, currently the only way is to get the root > node and then recreate the entire zipper structure. This seems > unnecessary. I think what you're asking for sounds very reasonable. It's also seems like it would have been obvious when creating the zipper API, so I wonder if it was really an oversight, or actually a design decision. Anyway, to "recreate the entire zipper structure" is not a particularly heavy operation. It simply creates a vector of 2 items (first is your tree, second is nil) and attaches some metadata to that. So it's constant time and not very heavy. --Chouser --~--~-~--~~~---~--~~ 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 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: Support for disabling forms (reader macro similar to CL's #-(and))
Mark Volkmann writes: > On Sun, Jan 25, 2009 at 1:43 PM, Rich Hickey wrote: >> On Jan 25, 1:43 pm, Jan Rychter wrote: >>> Meikel Brandmeyer writes: >>> > Am 25.01.2009 um 17:11 schrieb Zak Wilson: >>> >>> >> Clojure has that in the comment form: (comment (do (not (eval this >>> >>> > No. That's not equivalent. comment leaves a nil behind, while #* >>> > would not. >>> >>> > [:a (comment :b) :c] => [:a nil :c] >>> > [:a #* :b :c] => [:a :c] >>> >>> Exactly. In CL you can use #-(and) for anything, for example function >>> arguments. I use it like that way regularly while developing code. It >>> has to be a reader macro. >>> >> >> I'm not ready to add a features-like system to Clojure just yet, but >> am in favor of a single-form comment-out reader macro. >> >> Just need to pick a dispatch character: >> >> #- >> #/ >> #; >> >> other candidates? > > I prefer #; since ; is already the normal comment character. I would much rather see #-. 1. It makes logical sense to me (minus as in compile everything minus this form). 2. It doesn't mess up all the simple regexp engines that rely on knowing that anything after a ; is a comment. --J. --~--~-~--~~~---~--~~ 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 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: Support for disabling forms (reader macro similar to CL's #-(and))
Mark Volkmann writes: > On Sun, Jan 25, 2009 at 1:43 PM, Rich Hickey wrote: >> On Jan 25, 1:43 pm, Jan Rychter wrote: >>> Meikel Brandmeyer writes: >>> > Am 25.01.2009 um 17:11 schrieb Zak Wilson: >>> >>> >> Clojure has that in the comment form: (comment (do (not (eval this >>> >>> > No. That's not equivalent. comment leaves a nil behind, while #* >>> > would not. >>> >>> > [:a (comment :b) :c] => [:a nil :c] >>> > [:a #* :b :c] => [:a :c] >>> >>> Exactly. In CL you can use #-(and) for anything, for example function >>> arguments. I use it like that way regularly while developing code. It >>> has to be a reader macro. >>> >> >> I'm not ready to add a features-like system to Clojure just yet, but >> am in favor of a single-form comment-out reader macro. >> >> Just need to pick a dispatch character: >> >> #- >> #/ >> #; >> >> other candidates? > > I prefer #; since ; is already the normal comment character. I would much rather see #-, for two reasons: 1. It doesn't mess up all the simple regexp engines that rely on knowing that anything after a ; is a comment. 2. It makes logical sense to me (minus as in compile everything minus this form). Choosing #; means that authors of all editor support code, formatting or coloring code, javascript beautifiers, and so on will have to deal with this -- and most of them do not have a reader at hand. --J. --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---
Agent watchers on Refs
Hi Rich, all, Ever since the new implementation of watchers I've been itching to try out Cells again. It worked great for agents. I ran into a snag, though, when I tried to make cells out of refs. Here's an example. I make two refs: (def r1 (ref 1)) (def r2 (ref (+ 10 @r1))) Add a watcher so that r2 gets updated whenever r1 changes: (add-watcher r1 :send (agent nil) (fn [a r] (dosync (ref-set r2 (+ 10 @r) Seems to work: (println @r1 @r2) ;;=> 1 11 (dosync (ref-set r1 2)) (println @r1 @r2) ;;=> 2 12 Unless I go too fast: (do (dosync (ref-set r1 3)) (println @r1 @r2)) ;;=> 3 12 And I have to wait for the watcher to catch up: (println @r1 @r2) ;;=> 3 13 I guess I was hoping that the watcher on a ref would be called synchronously in the same transaction that modified the ref. I'm not sure if that's possible, or even desirable. I found a way around, but I had to abandon watchers in the process. So I suppose my question is, do watchers have to be agents? -Stuart Sierra --~--~-~--~~~---~--~~ 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 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: Support for disabling forms (reader macro similar to CL's #-(and))
#- makes sense (CL didn't always make things the wrong way :-) And indeed, #; *could* break a lot of already existing editors for a while -- Laurent 2009/1/25 Jan Rychter > > Mark Volkmann writes: > > On Sun, Jan 25, 2009 at 1:43 PM, Rich Hickey > wrote: > >> On Jan 25, 1:43 pm, Jan Rychter wrote: > >>> Meikel Brandmeyer writes: > >>> > Am 25.01.2009 um 17:11 schrieb Zak Wilson: > >>> > >>> >> Clojure has that in the comment form: (comment (do (not (eval > this > >>> > >>> > No. That's not equivalent. comment leaves a nil behind, while #* > >>> > would not. > >>> > >>> > [:a (comment :b) :c] => [:a nil :c] > >>> > [:a #* :b :c] => [:a :c] > >>> > >>> Exactly. In CL you can use #-(and) for anything, for example function > >>> arguments. I use it like that way regularly while developing code. It > >>> has to be a reader macro. > >>> > >> > >> I'm not ready to add a features-like system to Clojure just yet, but > >> am in favor of a single-form comment-out reader macro. > >> > >> Just need to pick a dispatch character: > >> > >> #- > >> #/ > >> #; > >> > >> other candidates? > > > > I prefer #; since ; is already the normal comment character. > > I would much rather see #-, for two reasons: > > 1. It doesn't mess up all the simple regexp engines that rely on knowing > that anything after a ; is a comment. > > 2. It makes logical sense to me (minus as in compile everything minus > this form). > > Choosing #; means that authors of all editor support code, formatting or > coloring code, javascript beautifiers, and so on will have to deal with > this -- and most of them do not have a reader at hand. > > --J. > > > > --~--~-~--~~~---~--~~ 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 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: zip/down bug?
Jan Rychter a écrit : > I think zip/down has a bug. It effectively does (when (children loc) > ...), and since in Clojure empty list isn't false, it ends up adding > nodes in my tree. > > Shouldn't it check for (when-not (empty? (children loc)) ...) ? > The children fn (passed to the zipper call) must return a seq, not a list. Christophe --~--~-~--~~~---~--~~ 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 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: time lies, even with doall
ok, those times make sense. The times are at least half the speed from the single pass, and more so because no recursion. So you have to do "dorun" to force the evaluation of each list? I was wondering about this, too. If you had done doall on the answer, it wouldn't have been a "deep execution", if you will. It would have just made sure you had two entries in the outer list . . . nevermind whether they were fully expanded? Also, I see how "do" was used to add "nil" as the return in filt-rem. I guess it wasn't needed in the second one because of the doruns? Do folks in the contrib group like this new implementation? On Sun, Jan 25, 2009 at 3:41 PM, Stuart Sierra wrote: > > Hi e, > > Most of the time is taken up by printing, which is why you see the > same times. Here's an example that gives the results you would expect. > > user> (def numbers (doall (take 50 (repeatedly #(rand-int > 3000) > #'user/numbers > user> (defn predicate [x] (< x 1500)) > #'user/predicate > user> (dotimes [i 5] > (time (do (filt-rem predicate numbers) nil))) > "Elapsed time: 1028.112 msecs" > "Elapsed time: 715.832 msecs" > "Elapsed time: 923.726 msecs" > "Elapsed time: 631.364 msecs" > "Elapsed time: 934.084 msecs" > nil > user> (dotimes [i 5] > (time (let [pair (separate predicate numbers)] > (dorun (first pair)) > (dorun (second pair) > "Elapsed time: 2694.912 msecs" > "Elapsed time: 2818.482 msecs" > "Elapsed time: 3087.375 msecs" > "Elapsed time: 2992.607 msecs" > "Elapsed time: 2959.005 msecs" > nil > > > -Stuart Sierra > > > > On Jan 25, 10:02 am, e wrote: > > The IRC channel folks helped me implement what we discovered was > > already called "separate" in contribs. My point was to do a partition > > that generated the two lists "(passes pred)" and "(fails pred)" in one > > pass without recursion. > > > > We ended up with: > > > > (defn filt-rem [pred coll] > > (loop [l1 () l2 () [f & r] coll] > > (if f > > (if (pred f) > > (recur (conj l1 f) l2 r) > > (recur l1 (conj l2 f) r)) > > (list l1 l2 > > > > -- the name reaming "filter and remove", I was thinking > > > > There's some branching there, so perhaps it's not the most efficient > > code. > > > > Here's what's in contrib, and as Tim showed me in the pquicksort > > discussion, that last bit could be replaced by "remove": > > > > (defn separate > > "Returns a vector: > >[ (filter f s), (filter (complement f) s) ]" > > [f s] > > [(filter f s) (filter (complement f) s)]) > > > > Well, the recursive one that does two passes blows away filt-rem, > > according to 'time'. But if I just count in my head, they both take > > about as long. > > > > Yes, I started throwing doall all over the place. The other thing is > > we definately aren't talking about milliseconds. I.m not trying to > > measure how much time is spent in the reader or compiler or whatever. > > I care about the user waiting for the answer, and that's what I'm > > trying to time. > > > > Here's what I'm seeing, even though I don't believe it: > > > > (def l1 (doall (take 5 (repeatedly #(rand-int 3000) ;;; I > > don't know if doall goes there, just shotgunning it at this point > > > > (time (filt-rem #(< % 1500) (doall l1))) I've tried doall in > > various places with no help > > "Elapsed time: 63.158 msecs"<-- no way. It took like 12 > > seconds > > > > (time (separate #(< % 1500) (doall l1))) ;; doall here > > actually did something even though already done above > > "Elapsed time: 12.701 msecs"<--- no way. 12 seconds, I > > counted. Definitely longer than 12 msecs. > > > > Questions: > > > > 1) Is there anything wrong with filt-rem or anything to improve it? > > 2) why are the times reportedly so different when I can tell they > > return in about the same amount of time? > > > > Thanks. > > > --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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 -~--~~~~--~~--~--~---
NewBie Q: doall forces eval and dorun not; but why?
Hi, I saw dorun and doall in core.clj as follows: That is, doall just calls dorun. My question is, how come doall does force eval and dorun does not. thanks in advance, -sun (defn dorun ([coll] (when (and (seq coll) (or (first coll) true)) (recur (rest coll ([n coll] (when (and (seq coll) (pos? n) (or (first coll) true)) (recur (dec n) (rest coll) (defn doall ([coll] (dorun coll) coll) ([n coll] (dorun n coll) coll)) --~--~-~--~~~---~--~~ 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 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: time lies, even with doall
On Jan 25, 2009, at 5:24 PM, e wrote: Do folks in the contrib group like this new implementation? To make contributions to clojure-contrib, you'll need to have a Contributor Agreement on file with Rich. Please see http://clojure.org/contributing . I think your implementation is an improvement over the current clojure.contrib.seq-utils/separate. I have some suggestions: - there's precedent for functions that do one thing or another based on a predicate to be named with a "-by" suffix. - using vectors for the intermediate results will allow the separated outputs to preserve the order of the input which might be helpful to some callers. Since it will still give good performance, I'd opt for that and promise it in the doc string. - you might also consider using the names first and rest for the destructured names you called f and r. I would imagine that's a bit controversial (because the local names would shadow useful functions), but arguably it would make the implementation easier to read. - returning a vector of vectors seems good to me. Here's an implementation: user> (defn separate-by [pred coll] (loop [in [] out [] [f & r] coll] (if f (if (pred f) (recur (conj in f) out r) (recur in (conj out f) r)) [in out]))) #'user/separate-by user> (separate-by odd? [1 2 3 4 5 6 7]) [[1 3 5 7] [2 4 6]] user> Whatever you propose will need a doc string. After Rich receives your Contributor Agreement and your name is up on the clojure.org/contributing page, please enter an issue against clojure-contrib noting that your alternate implementation for the current clojure.contrib.seq-utils/separate has higher performance while still being maintainable and correct. Include a complete copy of the code you propose, preferably as a patch. Once the issue is up, I'd follow up in this thread with the issue number requesting that Stuart consider resolving the issue by adopting your contribution. --Steve smime.p7s Description: S/MIME cryptographic signature
Turning a sequence of chars into a string.
Hi everybody, since I started using Clojure I've always felt that a small function for turning a sequence of chars into a string was missing. I'm currently using this one even though the name isn't quite right, but I didn't found better: (defn unseq [chars] (new String (into-array (. Character TYPE) chars))) So, is there a better way to accomplish this? Then, do someone have a better name for it? And finally, would this be worth including into Clojure or Clojure-contrib, with a better name? Thanks --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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: NewBie Q: doall forces eval and dorun not; but why?
On Jan 25, 2009, at 5:51 PM, wubbie wrote: I saw dorun and doall in core.clj as follows: That is, doall just calls dorun. My question is, how come doall does force eval and dorun does not. thanks in advance, Both force evaluation. Immediately before either returns, there is a fully realized sequence in memory. The difference is in their return value: - dorun returns nil. A call to dorun indicates: "all the work I want done is done in the evaluation of the elements of the sequence, I don't plan to work with the entire sequence after it's realized" - doall returns the head of the realized sequence. A call to doall indicates: "not only do I want the entire sequence realized, I also want to use the resulting sequence subsequently" It's good form to save or otherwise use the value returned by doall. --Steve smime.p7s Description: S/MIME cryptographic signature
Re: Turning a sequence of chars into a string.
On Jan 25, 2009, at 6:21 PM, budu wrote: So, is there a better way to accomplish this? Then, do someone have a better name for it? And finally, would this be worth including into Clojure or Clojure-contrib, with a better name? The usual way to do this is with "(apply str ...)" For example: user> (apply str (seq "Hello there")) "Hello there" user> Given this succinct way to accomplish the task, I think a new function isn't necessary. More generally, "into" and "empty" can be used to accomplish a kind of "unseq" operation for other kinds of collections. As I recall "empty" was created as a result of discussions about an "deseq" type of operation. --Steve smime.p7s Description: S/MIME cryptographic signature
Re: NewBie Q: doall forces eval and dorun not; but why?
2009/1/26 Stephen C. Gilardi > > On Jan 25, 2009, at 5:51 PM, wubbie wrote: > > I saw dorun and doall in core.clj as follows: > That is, doall just calls dorun. > My question is, how come doall does force eval and dorun does not. > thanks in advance, > > > Both force evaluation. Immediately before either returns, there is a fully > realized sequence in memory. > Are you sure ? I think the point of dorun is to prevent this case : with dorun, the elements of the sequence can be garbage collected once dorun goes on with the rest of the sequence, thus preventing to blow up the memory. > > The difference is in their return value: > > - dorun returns nil. A call to dorun indicates: > > "all the work I want done is done in the evaluation of the elements of the > sequence, I don't plan to work with the entire sequence after it's realized" > > - doall returns the head of the realized sequence. A call to doall > indicates: > > "not only do I want the entire sequence realized, I also want to use the > resulting sequence subsequently" > > It's good form to save or otherwise use the value returned by doall. > > --Steve > > --~--~-~--~~~---~--~~ 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 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: NewBie Q: doall forces eval and dorun not; but why?
Oh, I see the return value for doall. When I look at dorun it is different than lots of other functions. Unlinke lots of other functions that do conj, cons, etc. dorun just extract each element of coll. Is each element get evaluated if it's a code? Thanks -sun (defn dorun ([coll] (when (and (seq coll) (or (first coll) true)) (recur (rest coll On Jan 25, 6:21 pm, "Stephen C. Gilardi" wrote: > On Jan 25, 2009, at 5:51 PM, wubbie wrote: > > > I saw dorun and doall in core.clj as follows: > > That is, doall just calls dorun. > > My question is, how come doall does force eval and dorun does not. > > thanks in advance, > > Both force evaluation. Immediately before either returns, there is a > fully realized sequence in memory. > > The difference is in their return value: > > - dorun returns nil. A call to dorun indicates: > > "all the work I want done is done in the evaluation of the elements > of the sequence, I don't plan to work with the entire sequence after > it's realized" > > - doall returns the head of the realized sequence. A call to doall > indicates: > > "not only do I want the entire sequence realized, I also want to use > the resulting sequence subsequently" > > It's good form to save or otherwise use the value returned by doall. > > --Steve > > smime.p7s > 3KViewDownload --~--~-~--~~~---~--~~ 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 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: changes to test_clojure and test_contrib
I have some tests ready for test_clojure. I asked Rich for SVN access rights. There is gonna be more tests soon :-) Frantisek On Sun, Jan 25, 2009 at 8:55 PM, Stuart Halloway wrote: > > In SVN 412 I have made the following changes to contrib: > > * a test_contrib.clj file which does for contrib what test_clojure.clj > does for clojure > * a test_clojure task in build.xml > * a test_contrib task in build.xml > * a test task to aggregate all test tasks > > This is *very* minimal, but I wanted it so I could TDD some other > changes I am making to contrib. Feedback or further improvement most > welcome. > > Let's write some tests! > > 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 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: what's the typical usage of fn constantly
Following James's description, I would image constantly's implementation to look something like the following. (defn constantly [value] #(identity value)) If you haven't seen the # macro before, the form below is equivalent. (defn constantly [value] (fn [] (identity value))) Making use of Chris Houser's fine repl-utils library, you can easily view the source at the REPL. user=> (clojure.contrib.repl-utils/source constantly) (defn constantly "Returns a function that takes any number of arguments and returns x." [x] (fn [& args] x)) Seems I wasn't too far off, the canonical version allows any number of args to be passed, but still just returns the value given at the time of declaration. I think it's safe to view constantly as a function wrapper around 'identity'. user=> (clojure.contrib.repl-utils/source identity) (defn identity "Returns its argument." [x] x) That is, I would view constantly to be the same as identity except it returns a function which can be passed around, rather than the value itself. Finally, you could just as well do '#(identity the-value)' and get the same result. user=> (= (#(identity "ab")) ((constantly "ab"))) true Sorry if I beat this to death; some of it was for my own learning and benefit. On Jan 25, 2:08 pm, wubbie wrote: > thanks James, > I'll have a look. > > -sun > > On Jan 25, 2:00 pm, James Reeves wrote: > > > On Jan 25, 5:34 pm, wubbie wrote: > > > > What's the typical usage of fn constantly ? > > > When you need a function that constantly returns the same result :) > > > That probably doesn't tell you any more than you know already, so I'll > > give you a real world use. My rnd-utils library has a function > > generating random strings that match a regular expression. It does > > this by converting a regex into a sequence of functions, and then > > concatenating the results into a string. > > > So a regex like "ab[def]" would be converted into two functions: > > [(constantly "ab") (rnd-choice "def")] > > > This can then be turned into a string using: (apply str (map apply > > function-sequence)) > > > - James --~--~-~--~~~---~--~~ 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 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: NewBie Q: doall forces eval and dorun not; but why?
On Jan 25, 2009, at 6:45 PM, Laurent PETIT wrote: 2009/1/26 Stephen C. Gilardi Both force evaluation. Immediately before either returns, there is a fully realized sequence in memory. Are you sure ? I think the point of dorun is to prevent this case : with dorun, the elements of the sequence can be garbage collected once dorun goes on with the rest of the sequence, thus preventing to blow up the memory. Right you are! Thanks for the correction. I was recalling the case of "filter" retaining the head even when it wasn't intended to. In reading the code for dorun, I incorrectly concluded that the "coll" argument unavoidably kept the head as well. Instead, recur takes care of that and dorun works exactly as one might hope. --Steve smime.p7s Description: S/MIME cryptographic signature
Re: NewBie Q: doall forces eval and dorun not; but why?
then, back to my original question. They (dorun do all) differe ONLY in return value. Then how come one forces eval and the other not? -sun On Jan 25, 7:18 pm, "Stephen C. Gilardi" wrote: > > On Jan 25, 2009, at 6:45 PM, Laurent PETIT wrote: > > >> 2009/1/26 Stephen C. Gilardi > > >> Both force evaluation. Immediately before either returns, there is > >> a fully realized sequence in memory. > > >> Are you sure ? I think the point of dorun is to prevent this case : > >> with dorun, the elements of the sequence can be garbage collected > >> once dorun goes on with the rest of the sequence, thus preventing > >> to blow up the memory. > > Right you are! Thanks for the correction. I was recalling the case of > "filter" retaining the head even when it wasn't intended to. In > reading the code for dorun, I incorrectly concluded that the "coll" > argument unavoidably kept the head as well. > > Instead, recur takes care of that and dorun works exactly as one might > hope. > > --Steve > > smime.p7s > 3KViewDownload --~--~-~--~~~---~--~~ 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 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: what's the typical usage of fn constantly
thanks for the insight! On Jan 25, 7:06 pm, "rzeze...@gmail.com" wrote: > Following James's description, I would image constantly's > implementation to look something like the following. > > (defn constantly [value] #(identity value)) > > If you haven't seen the # macro before, the form below is equivalent. > > (defn constantly [value] (fn [] (identity value))) > > Making use of Chris Houser's fine repl-utils library, you can easily > view the source at the REPL. > > user=> (clojure.contrib.repl-utils/source constantly) > (defn constantly > "Returns a function that takes any number of arguments and returns > x." > [x] (fn [& args] x)) > > Seems I wasn't too far off, the canonical version allows any number of > args to be passed, but still just returns the value given at the time > of declaration. I think it's safe to view constantly as a function > wrapper around 'identity'. > > user=> (clojure.contrib.repl-utils/source identity) > (defn identity > "Returns its argument." > [x] x) > > That is, I would view constantly to be the same as identity except it > returns a function which can be passed around, rather than the value > itself. > > Finally, you could just as well do '#(identity the-value)' and get the > same result. > > user=> (= (#(identity "ab")) ((constantly "ab"))) > true > > Sorry if I beat this to death; some of it was for my own learning and > benefit. > > On Jan 25, 2:08 pm, wubbie wrote: > > > thanks James, > > I'll have a look. > > > -sun > > > On Jan 25, 2:00 pm, James Reeves wrote: > > > > On Jan 25, 5:34 pm, wubbie wrote: > > > > > What's the typical usage of fn constantly ? > > > > When you need a function that constantly returns the same result :) > > > > That probably doesn't tell you any more than you know already, so I'll > > > give you a real world use. My rnd-utils library has a function > > > generating random strings that match a regular expression. It does > > > this by converting a regex into a sequence of functions, and then > > > concatenating the results into a string. > > > > So a regex like "ab[def]" would be converted into two functions: > > > [(constantly "ab") (rnd-choice "def")] > > > > This can then be turned into a string using: (apply str (map apply > > > function-sequence)) > > > > - James > > --~--~-~--~~~---~--~~ 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 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: NewBie Q: doall forces eval and dorun not; but why?
On Jan 25, 2009, at 7:35 PM, wubbie wrote: then, back to my original question. They (dorun do all) differe ONLY in return value. Then how come one forces eval and the other not? Both force evaluation. Is there something that makes you think otherwise? In the case of dorun, the members of the sequence are evaluated and then immediately thrown away. In the case of doall, the members of the sequence are evaluated and the entire sequence is kept in memory and returned. None of the members are thrown away because the "coll" argument (which is also the returned value) holds a "reference" (in the java sense) to the first item, the first item holds a reference to the second item, and so on all the way down the chain. --Steve smime.p7s Description: S/MIME cryptographic signature
Re: NewBie Q: doall forces eval and dorun not; but why?
On Jan 25, 2009, at 7:47 PM, Stephen C. Gilardi wrote: In the case of dorun, the members of the sequence are evaluated and then immediately thrown away. "Immediately" overstates it... they are left unreferenced and get thrown away when the Java garbage collector notices they are unreferenced and collects them as garbage. --Steve smime.p7s Description: S/MIME cryptographic signature
Re: NewBie Q: doall forces eval and dorun not; but why?
Thanks Steve for the clear explanation. Now I get it... But a question on "... are evaluated and then immediately thrown away". I believe the evaluation is done in (or (first coll) true)). My question is that extracting out "first coll" is same as evaluating "first coll"? For example (first '( (+ 1 2) (+ 3 4))) returns (+ 1 2) not the evaluated result, which is 3. Wait... I just tried (first (list (+ 1 2) (+ 3 4))) and got 3! So (list a b c) is different than '( a b c)? I thought they are equivalent! -sun On Jan 25, 7:47 pm, "Stephen C. Gilardi" wrote: > On Jan 25, 2009, at 7:35 PM, wubbie wrote: > > > then, back to my original question. > > They (dorun do all) differe ONLY in return value. > > Then how come one forces eval and the other not? > > Both force evaluation. Is there something that makes you think > otherwise? > > In the case of dorun, the members of the sequence are evaluated and > then immediately thrown away. > > In the case of doall, the members of the sequence are evaluated and > the entire sequence is kept in memory and returned. None of the > members are thrown away because the "coll" argument (which is also the > returned value) holds a "reference" (in the java sense) to the first > item, the first item holds a reference to the second item, and so on > all the way down the chain. > > --Steve > > smime.p7s > 3KViewDownload --~--~-~--~~~---~--~~ 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 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: NewBie Q: doall forces eval and dorun not; but why?
On Jan 25, 2009, at 8:05 PM, wubbie wrote: Wait... I just tried (first (list (+ 1 2) (+ 3 4))) and got 3! So (list a b c) is different than '( a b c)? I thought they are equivalent! Right, as your experiment shows, the ' in '(a b c) quotes both the list itself and all of its contents. Using vectors to hold your data can be a convenient way to experiment because you don't have to worry about avoiding the special evaluation rules for lists. user=> [(+ 1 2) (+ 3 4)] [3 7] One strategy for working with Clojure is to favor using: - lists mostly for function calls, - vectors, maps, and sets mostly for collecting data, and - seqs (and the seq functions) mostly for manipulating data. Clojure's rich set of literal syntax for collections other than lists is very helpful in keeping code readable while following that strategy. --Steve smime.p7s Description: S/MIME cryptographic signature
Re: time lies, even with doall
ok, I'll check that stuff out. Thanks. It occurs to me this is being compared to something in ruby called partition. I like that name. "partition-by" ... but maybe it was opted to use the simpler name, which I can appreciate. On that subject, I know "filter" is standard from other languages like Haskell, but I had to learn that it meant "retain-if". To me, "filter" sounds synonymous with "remove". Other candidates: "keep", "preserve". Also, that "-by" convention sounds right for partition or separate, but in the case of filter and remove, "if" sounds better. I suggest breaking from the "filter" tradition and going with "retain-if" and "remove-if". On Sun, Jan 25, 2009 at 6:10 PM, Stephen C. Gilardi wrote: > > On Jan 25, 2009, at 5:24 PM, e wrote: > > Do folks in the contrib group like this new implementation? >> > > To make contributions to clojure-contrib, you'll need to have a Contributor > Agreement on file with Rich. Please see http://clojure.org/contributing . > > I think your implementation is an improvement over the current > clojure.contrib.seq-utils/separate. > > I have some suggestions: > >- there's precedent for functions that do one thing or another based > on a predicate to be named with a "-by" suffix. >- using vectors for the intermediate results will allow the > separated outputs to preserve the order of the input which might be helpful > to some callers. Since it will still give good performance, I'd opt for that > and promise it in the doc string. >- you might also consider using the names first and rest for the > destructured names you called f and r. I would imagine that's a bit > controversial (because the local names would shadow useful functions), but > arguably it would make the implementation easier to read. >- returning a vector of vectors seems good to me. > > Here's an implementation: > > user> (defn separate-by [pred coll] > (loop [in [] out [] [f & r] coll] > (if f > (if (pred f) > (recur (conj in f) out r) > (recur in (conj out f) r)) > [in out]))) > > #'user/separate-by > user> (separate-by odd? [1 2 3 4 5 6 7]) > [[1 3 5 7] [2 4 6]] > user> > > Whatever you propose will need a doc string. > > After Rich receives your Contributor Agreement and your name is up on the > clojure.org/contributing page, please enter an issue against > clojure-contrib noting that your alternate implementation for the current > clojure.contrib.seq-utils/separate has higher performance while still being > maintainable and correct. Include a complete copy of the code you propose, > preferably as a patch. > > Once the issue is up, I'd follow up in this thread with the issue number > requesting that Stuart consider resolving the issue by adopting your > contribution. > > --Steve > > --~--~-~--~~~---~--~~ 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 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: NewBie Q: doall forces eval and dorun not; but why?
interesting to me that <> wasn't used for anything to add to the "literal syntax". folks in another thread were using sequences for set theory. But maybe there needs to be a set notation. If that makes sense, {} should be sets, just like in math, <> should be vectors, just like in math, and [] could be maps. I know, I know, it's kinda late to be arguing to change this stuff. Another idea that fits in better would be to use <> as an alternative to quoting a list . . . and still not do anything for sets. On Sun, Jan 25, 2009 at 8:25 PM, Stephen C. Gilardi wrote: > > On Jan 25, 2009, at 8:05 PM, wubbie wrote: > > Wait... I just tried (first (list (+ 1 2) (+ 3 4))) and got 3! >> So (list a b c) is different than '( a b c)? I thought they are >> equivalent! >> > > Right, as your experiment shows, the ' in '(a b c) quotes both the list > itself and all of its contents. > > Using vectors to hold your data can be a convenient way to experiment > because you don't have to worry about avoiding the special evaluation rules > for lists. > > user=> [(+ 1 2) (+ 3 4)] > [3 7] > > One strategy for working with Clojure is to favor using: > >- lists mostly for function calls, >- vectors, maps, and sets mostly for collecting data, and >- seqs (and the seq functions) mostly for manipulating data. > > Clojure's rich set of literal syntax for collections other than lists is > very helpful in keeping code readable while following that strategy. > > --Steve > > --~--~-~--~~~---~--~~ 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 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: NewBie Q: doall forces eval and dorun not; but why?
Hi, Am 26.01.2009 um 06:05 schrieb e: interesting to me that <> wasn't used for anything to add to the "literal syntax". folks in another thread were using sequences for set theory. But maybe there needs to be a set notation. If that makes sense, {} should be sets, just like in math, <> should be vectors, just like in math, and [] could be maps. I know, I know, it's kinda late to be arguing to change this stuff. Another idea that fits in better would be to use <> as an alternative to quoting a list . . . and still not do anything for sets. There is already literal syntax for all the collection types: - [] => vector - {} => hash-map - #{} => set What are you missing? Try to blend out experiences from other fields. Eg. we never used <> for vectors in math, only (). So even this comparison is only your personal experience. It's good to have such experience when learning a new language, but it should not get into your way. Whenever you end up with "But in this other field/language we do/have/can ", you should take a step back and forget about the other field/language and look simply at Clojure. We cannot cater all the previous experiences of all the Clojure users Just my 2¢. Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: (clojure.contrib.lazy-seqs/combinations) should return [[]], not nil?
OK, cartesian_product it is. Two comments on your version. First, unlike mine (and the current "combinations"), it takes a single argument, a seq of seqs (rather than multiple seq arguments); which of these ways is preferred? Second, I had the clauses of my for loop backwards, which was slowing things down. I think this version: (defn combinations "Take a seq of seqs and return a lazy list of ordered combinations (pick 1 from each seq)" [seqs] (if (empty? seqs) '(()) (for [rst (combinations (rest seqs)) item (first seqs)] (cons item rest is actually significantly faster than the iterative one you posted (and also much simpler); do your benchmarks agree? On Jan 24, 12:47 am, Mark Engelberg wrote: > On Fri, Jan 23, 2009 at 11:43 PM, wrote: > > I think the usual mathematical name is be cartesian-product (or maybe > > cross-product), although selections is OK with me too. > > Yes, now that you've reminded me, I agree that cartesian-product is > the usual mathematical name, and that would probably be my first > choice. --~--~-~--~~~---~--~~ 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 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.contrib.lazy-seqs/combinations) should return [[]], not nil?
For simple inputs, the two approaches have similar performance. On complex inputs, my tests show the iterative version tends to run about twice as fast. Try running on an extreme input like: ["ACDFG" "A" "B" "C" "D" "E" "F" "ABCD" "G" "H" "I" "ABEG" "J" "K" "BCDE" "L" "ABCDG" "M" "EF" "NABC" "ABCDFG" "ABDEFG" "DGHI" "ABCDEFG"] and let me know if you also see the 2x performance difference. --~--~-~--~~~---~--~~ 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 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 -~--~~~~--~~--~--~---