Re: :require farms in Clojure?
On Jul 20, 4:19 pm, Meikel Brandmeyer m...@kotka.de wrote: I think he wants more something like this: (ns require.farm) (def xxx '[[foo.bar [a :as a] [b :as b]] frob.nicate]) (def yyy '[[foo.bar.c :as c]]) (ns require.userA (:require [require.farm :as requires])) (apply require requires/xxx) Yes -- this is the kind of thing I was wondering about (although Chas' answer is immediately useful too--thanks). At this point I'm wondering if this is an idiomatic way to work with Clojure namespaces especially in larger projects with many sub- components as namespaces? Maybe one day we could have: (ns myproject (:require subproject.* :as :suffix) to require subproject.foo1 subproject.foo2... Thanks Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
:require farms in Clojure?
Hi, In larger Clojure projects with nested namespaces I've found there are less namespace pollution issues if I avoid (ns... :use...) forms in preference to (ns... :require...) forms. This approach sometimes leads to namespace constructs like: (ns myfuns (:require [foo.baz.a :as a] [foo.baz.b :as b] [foo.baz.c :as c...])) Is there an idiomatic way of coalescing these :require clauses into a :require farm that can be simply :require'd or is this the wrong way to manage namespaces in Clojure projects? Any advice much appreciated, Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Looking for examples of using Java iterators from Clojure...
Hi, I'd like to make use of Java classes implementing the Java2D PathIterator interface: http://download.oracle.com/javase/6/docs/api/java/awt/geom/PathIterator.html Which leads to a serious impedance mismatch between immutable Clojure data structures and the iterator's approach of calling next() until isDone() and using currentSegment() to retrieve the point coordinates. I'd guess this kind of iterator is widely used in the Java world, so can some kind person point to an example of Clojure code using a Java iterator in this way? Thanks in advance, Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Idiomatic way to reference a bundled data file from Clojure source?
Hi, I'd like to bundle a collection of (JSON) datafiles with a Clojure project source tree so that Clojure functions can reliably find and open those datafiles. What's the idiomatic way of going about this? In the past with other languages I've used tricks like Ruby's .dirname(__FILE__)/... construct but this kind of approach doesn't seem a good fit for Clojure or for the JVM facilities it provides. Can anyone point to a Clojure project that does this well? Thanks, Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Idiomatic way to reference a bundled data file from Clojure source?
On Jun 29, 12:17 pm, Stephen C. Gilardi squee...@mac.com wrote: I'd like to bundle a collection of (JSON) datafiles with a Clojure project source tree so that Clojure functions can reliably find and open those datafiles. What's the idiomatic way of going about this? Many thanks to Dave and Stephen for your answers--just what I needed. Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Hygenic approach for using Java2D from Clojure?
Hi, I'd like to use Java2D objects in a Clojure application. I understand that these mutable objects will be operating in a Clojure environment where immutability is the order of the day, and this is likely to cause problems. Can someone point me to some good examples of, or techniques for safely using mutable Java objects in Clojure--especially with Clojure parallel programming constructs in mind. Thanks in advance, Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: 2D graphics options with Clojure?
On Apr 30, 5:54 pm, Nathan Sorenson n...@sfu.ca wrote: Batik can serialize to both PNG and PDF.http://xmlgraphics.apache.org/batik/ I currently use Batik in a clojure project doing a lot of drawing of 2d vector-based images. It's a very extensive library but it suits my needs well. Do you have any Clojure examples of Batik use I could look at? Thanks, Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
2D graphics options with Clojure?
Hi, I'm developing a Clojure project that loads and creates a bunch of simple 2D geometry (lines, polygons, beziers, text etc). I need to create in a batch-style way high quality 2D renderings of that geometry, firstly as PNG files and secondly as PDF files. What are my options for doing this from Clojure? So far I can see it might be done with Java2D as I think this can be used server-side to create the PNG files, but not sure about the PDFs. I believe I can use Incanter's wrapping of the Processing libraries for the PNG and again I'm not sure about the PDF option. The Cairo toolkit is also an option via the Gnome Java bindings and Java interop? Are there other options that I'm missing that anyone would like to report on? Thanks in advance, Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
How to access specific java.awt.Color constructor?
Hi, I'm trying to create a java.awt.Color class instance from within Clojure, using this constructor: Color(ColorSpace cspace, float[] components, float alpha) But always end up with a No matching ctor found for class java.awt.Color exception. I can create the ColorSpace instance as I expected, but I think I'm missing something with the rest of the Color constructor. I've tried changing the components to a vector of floats or a Java array of floats with no luck. This is with Clojure 1.2 and the Java Platform SE 6 AWT classes. Any advice much appreciated. Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: How to access specific java.awt.Color constructor?
On Apr 10, 8:35 am, Alan a...@malloys.org wrote: You probably weren't putting it into a java float array, but instead a Float array (boxed type). Here's a repl session doing what you want. I don't know anything about colorspaces so it's probably nonsense, but it creates a Color with that constructor. Thanks Alan -- I realize now there's a subtle but important distinction there when doing Java interop. Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Polymorphic functions in Clojure (or how to stop thinking in objects)...
Hi, I wanted to take the opportunity to thank the people who responded to my question on thinking beyond O-O. The replies form a very useful slice through Clojure design strategies and idiomatic use of the language. Thanks! Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Polymorphic functions in Clojure (or how to stop thinking in objects)...
Hi, I'd like to create a simple library of drawable shapes: lines, circles and rectangles. I've placed each type of shape in its own namespace with functions that operate on that shape kind: (ns myshapes.line) (defn line ... creates new line ...) (defn draw ... draws a line ...) To keep things simple a line is just a vector of two points and circles and rectangles are just structs. I'd also like to have a sequence of shapes called a picture: (ns myshapes.picture) (defn picture ... returns picture sequence from args ...) (defn draw ... draws whole picture) The problem I have is with the myshapes.picture/draw function. As a Clojure newb I keep wanting to think of this like a polymorphic function in the O-O world that relies on each sequence member having a draw function. What's the idiomatic way of handling a situation like this in Clojure? Do I need to use richer data structures than vectors and structs for the shapes so they carry some kind of type information? I can see how a draw multi-method would work if the individual shapes could be distinguished, or am I going about this the wrong way? Any advice much appreciated, Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Idiomatic way to handle name shadowing?...
Hi, This is a newb question so apologies in advance if I haven't read enough Clojure code yet to see the answer. Suppose I need mathematical 2D vector functions: (ns geometry.vector) (defstruct vector :x :y) (defn + Add vectors v and w, yielding a vector [ v w ] (...)) Which leads to the core vector function being shadowed by my struct and the core + function shadowed by my function. What is the idiomatic Clojure approach for handling this situation? Is it through careful use of :require and :import parts of a (ns ...) form? I've also seen instances of naming changes to avoid the problem, e.g. (defstruct vector ...) and (defn vector+ ...) but not sure if that's making best use of Clojure namespaces? Any advice much appreciated, Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Idiomatic way to handle name shadowing?...
On Mar 11, 8:35 am, Alan a...@malloys.org wrote: Suppose I need mathematical 2D vector functions: (ns geometry.vector) (defstruct vector :x :y) (defn + Add vectors v and w, yielding a vector [ v w ] (...)) Which leads to the core vector function being shadowed by my struct and the core + function shadowed by my function. What is the idiomatic Clojure approach for handling this situation? Is it through careful use of :require and :import parts of a (ns ...) form? user= (ns math (:refer-clojure :rename {vector cvector})) nil math= vector java.lang.Exception: Unable to resolve symbol: vector in this context (NO_SOURCE_FILE:0) math= (def vector identity) #'math/vector math= (vector 10) 10 math= (cvector 10) [10] Thanks for that -- please bear with me on this: does that mean that given the flexible options available in the (ns...) form as shown here, Clojure developers don't need to choose non-shadowed names like vector or (defn vector+), but rather use the more natural forms and use (ns...) clauses to make everything clear as needed? Thanks, Stu -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Transient Data Structures
I really, really like this feature. My only complaint is that you have to use different names for the modifying functions. If the function signatures will be identical to their non-transient variants, then I guess the primary arguments would be: * Clojure convention for names of functions with side-effects, * An additional interface check in conj/assoc? But if after calling (conj v 1), you can't use the 'v' reference anymore, then did you really cause a side effect? Its another tree falling in the woods situation. Thanks, Stu On Wed, Aug 5, 2009 at 9:05 AM, Rich Hickey richhic...@gmail.com wrote: On Tue, Aug 4, 2009 at 10:13 PM, John Harropjharrop...@gmail.com wrote: On Tue, Aug 4, 2009 at 5:50 PM, Rich Hickey richhic...@gmail.com wrote: On Aug 4, 4:31 pm, John Harrop jharrop...@gmail.com wrote: What about things like: (persistent! (reduce (fn [x [i v]] (assoc! x i v)) (transient (vec (repeat 0 (reduce max (map first coll-of-index-val-pairs) coll-of-index-val-pairs)) Yes, that's completely fine intended usage, as the return value of the reducing fn becomes an argument to the next call. which is just the transientification of Nice word - transientification. Thanks. Of course, this makes me think of ways to possibly speed up other operations. For example: (defn vmap* [fun vect] (let [c (count vect)] (loop [out (transient []) i 0] (if (= i c) out (recur (conj! out (fun (nth vect i))) (inc i)) (defn vmap [fun vect] (persistent! (vmap* fun vect))) Vector in, vector out, conj'd up using a transient. Mapping into vectors and similar ops are coming, although nothing like vmap* would ever be exposed. And, of course: (defn vpmap [fun vect] (loop [out (vmap* #(future (fun %)) vect) i (dec (count vect))] (let [o2 (assoc! out i @(nth out i))] (if (zero? i) (persistent! o2) (recur o2 (dec i) Note that this last manipulates a transient vector in a single thread, though other threads (from the agent pool) calculate a bunch of futures that are stored in it. The transient vector of futures is generated using the vmap* from above, and then the futures are replaced with their values in-place by the loop in vpmap, before this persistentizes and returns that vector. The future-dereferencing loop works backwards from the end of the vector in case zero? is a quicker test than a general equality test. This is likely on hardware that implements an equality test as a subtraction followed by a zero test, because it eliminates the subtraction. On the other hand, hardware with a 1-cycle equality test of 32-bit ints is plausible, as is hardware that optimizes forward traversal of vectors, so I can't vouch for that being an optimization. The first loop has to go forward to conj up the output vector without reversing it, though. There is already a very nice pvmap in the par branch that uses ForkJoin. I strongly recommend against trying to write parallel ops with transients - that's not what they are for. What's nice about pvmap is that, just like transients, it also takes, manipulates, and returns ordinary Clojure vectors (unlike the old parallel lib which copied into and out of ForkJoin's ParallelArrays). The goal is to make using the normal data structures as powerful as possible, and not needing to switch to something else for performance. 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 Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: why is io! not enforced?
This won't work unfortunately, because it means that the in-memory transaction has already commited before the disk write is performed by the agent. If the application crashed at that point, your write was not durable. -- Sent from my Palm Pre ataggart wrote: On Jun 20, 4:59 pm, Rowdy Rednose wrote: On a side-note: I actually think it can make sense to do io in transactions in Clojure, and I believe (knowing that transactions can be replayed) it is possible to use that to e.g. implement a transaction log written to disk that could be used to rebuild the data in case of a crash. Use agents. When inside a running transaction, all agent dispatches are held until the transaction commits. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Metadata for Any Object
Hey gang, Metadata support for pure Java objects is not currently supported, because it requires a modification to the object. Additionally, only some Clojure objects support metadata, due to the necessity of implementing the IMeta interface. This can be confusing for new users, and eliminates some of the utility. Instead of attaching the metadata directly to the object, what if the metadata was stored outside the object, in a global map of {object metadata, ...}? In order to handle garbage collection, something similar to Java's WeakHashMap could be used, with the object itself as the key. I know global state is Considered Harmful, but I think this would clarify the usage of metadata, and remove duplication in the implementation of Clojure. Thoughts? Stu --~--~-~--~~~---~--~~ 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: [Discuss] Contribs with dependencies
I agree. I think the breaking into modules approach is the only scalable solution. Someone else mentioned that clojure-contrib is/shouldbe an incubating area for core, which seems reasonable. There should be a little more pushback when a project wants to make it into contrib, and it should already be organized such that its dependencies would be well known if it wanted to make it out of 'incubation' and into core. On Tue, Apr 14, 2009 at 5:02 PM, Howard Lewis Ship hls...@gmail.com wrote: I'd say to refactor clojure-contrib into a number of seperate modules; individual modules (each with its own pom) could have their own dependencies. Thus if you choose clojure-contrib-freechart, you get that JAR (or compiled Clojure sources) plus the jfreechart dependency. In this way you are using the good part of Maven: transitive dependency management. On Tue, Apr 14, 2009 at 5:19 AM, Rich Hickey richhic...@gmail.com wrote: I've been thinking recently about contribs with dependencies. I think it's very important to have layers - e.g. core depends only on JDK 1.5, contrib only on core. Lately there have been some ideas centering around Joda Time, [Parallel]Colt, AWS, JFreeChart, Fork/Join etc. I'd like to start a discussion about how best to support the contributions of libraries that depend on things not in the JDK. Obviously, without care and rules it could get crazy quickly, and I want to avoid the kitchen-sink effect. It is very important that things remain [truly, not just apparently] simple. Looking for suggestions, Rich -- Howard M. Lewis Ship Creator of Apache Tapestry Director of Open Source Technology at Formos --~--~-~--~~~---~--~~ 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: advice needed converting large files to xml
If you write your CSV - XML processing as a function, you could pmap ( http://clojure.org/api#pmap) that function across the list of input files. pmap will transparently create the threads as needed, and it will probably be enough to saturate your disk. Thanks, Stu On Mon, Mar 16, 2009 at 5:56 PM, Brian Doyle brianpdo...@gmail.com wrote: I've been using Clojure for about 6 months now and really like it. I am somewhat new to multi-threading and using any of the parallel features in Clojure though. I have a situation where I need to convert 7 files from CSV to XML. Each one of these files is about 180MB apiece in size. I have dual core machine with 2GB of RAM and would like some advice on the best strategy for processing these files in a way that really utilizes both cores and my memory to really speed up the processing.I'm sure this isn't the best way, but I've only come up with starting up two threads at first, having each thread open up a file, call line-seq on that file, write out the XML for each line and then go to the next file when it's complete. Any advice would be great. 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: Bytecode optimization
Rich has done a lot of work to make sure that when you are working with primitives, the JVM bytecode ends up being very similar to what Java would generate. See http://clojure.org/java_interop#toc36 Thanks, Stu On Thu, Mar 12, 2009 at 6:20 PM, Howard Lewis Ship hls...@gmail.com wrote: Well, at some point I'll open up the code and check. Though I'll be overly tempted to write some comments, fix the indentation and write some tests if I do! On Thu, Mar 12, 2009 at 2:36 PM, Jarkko Oranen chous...@gmail.com wrote: On Mar 12, 11:15 pm, Howard Lewis Ship hls...@gmail.com wrote: I have to wonder a bit about the ability to optimize. Everything boils down to one of the seven or so basic forms. That's a lot of function calls to do even small things, like adding numbers. You might think that simple math would be optimized and inlined, but it isn't: Clojure user= (doc +) - clojure.core/+ ([] [x] [x y] [x y more]) Returns the sum of nums. (+) returns 0. nil user= (ns clojure.core) #Namespace clojure.core clojure.core= (defn + [x y] (* x y)) #'clojure.core/+ clojure.core= (+ 3 5) 15 clojure.core= This implies, to me, that Clojure is doing a full functional call, with dynamic lookup via the namespace, even for +. I think this is mistaken. Sure, for (+ foo bar) calls in the repl Clojure will do a full lookup, but if you have addition in a tight loop, the JVM should notice this and optimise it further. (I think Clojure also does some kind of caching.) You can also use type casts to make clojure use primitive instead of boxed math, bringing performance very close to Java. Now, it's probably true that the most straightforward Clojure implementation of an algorithm is likely not quite as fast as the Java equivalent, with a few tricks, you can often get pretty close. I don't have very in-depth knowledge of how Clojure handles these performance issues, but I believe your assumption is overly pessimistic. :) -- Jarkko -- Howard M. Lewis Ship Creator Apache Tapestry and Apache HiveMind --~--~-~--~~~---~--~~ 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: Performance tips for Clojure
There is a interface 'Counted' that a lot of Clojure data structures implement to indicate that they provide O(1) for (count). Thanks, Stu On Fri, Mar 13, 2009 at 4:59 AM, Christophe Grand christo...@cgrand.netwrote: Christian Vest Hansen a écrit : I think that count is O(n) for lists, no? Count is O(1) for lists but O(n) for a chain of conses. Clojure user= (let [l (apply list (range 10))] (time (dotimes [_ 100] (count l Elapsed time: 169.710116 msecs nil user= (let [l (apply list (range 40))] (time (dotimes [_ 100] (count l Elapsed time: 167.664046 msecs nil user= (let [l (reduce #(cons %2 %1) nil (range 10))] (time (dotimes [_ 100] (count l Elapsed time: 662.121862 msecs nil user= (let [l (reduce #(cons %2 %1) nil (range 100))] (time (dotimes [_ 100] (count l Elapsed time: 5316.110567 msecs nil -- Professional: http://cgrand.net/ (fr) On Clojure: http://clj-me.blogspot.com/ (en) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com 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: Laziness madness
Laziness hit home for me in Clojure when I noticed that one of our Java library functions, looking for a Collection, had happily accepted a Clojure (map ...) object which was going to expand a small set of integers into much larger objects. Because Clojure deferred the work, they were only generated when they were actually needed, and saved memory the rest of the time. Thanks, Stu On Mon, Mar 2, 2009 at 1:17 AM, Laurent PETIT laurent.pe...@gmail.comwrote: Hello, The way I think about it is am I in a portion of code that does pure functional stuff, or am I doing side effects ? A pure functional stuff resembles a computation, but not the storage part, or the part that gets the stuff from the outside (that is, no input / output stuff). doing side effects is when your function not only responds to a call to it by reading its input data and computing a new one that it returns, but also when it reads the input data, does some stuff to change the world (by accessing functions that will permanently change the world), and also (maybe) return a value. In this case, generally, comes with the non pure stuff the need to control the flow of execution of your program. That is : function A must be called before function B, and the effects of A on the world must have been realized before function B can run. In your case, you're calling add-watch which is clearly (to me) a side-effect function because it adds watchers to a long list of watchees by modifying them in place (side-effect). Generally speaking, if this talk about side-effect free function is still a little bit unclear to you, here are some smells to guess if a given function is pure or not : - does the function return a value (different from nil) ? If no - probably a function with side effect .. or a function that really does nothing ! - does the function return newly computed values ? If no - probably a function with side effect .. or a function that really does nothing ! (please note that the inverse is not true : you can't say that a function is pure just because it returns a new computed value of something) I would like to add a third rule to this list, but currently you will not encounter it for a lot of cases, yet it is correct in a number of case and I think it applies correctly to those cases : - does the function implementation use calls to functions ending with a ! ( e.g. set!) : those functions are performing side effects by permanently changing the value of something in the world. HTH, -- Laurent 2009/3/2 max3000 maxime.lar...@gmail.com Hi, I find the laziness in clojure very hard to wrap my head around. I understand the idea and it's probably nice in theory. However, in real life it doesn't seem really useful beyond hardcore mathematical problems. Case in point, I just spent 2 hours debugging a piece of code (shown below) that seemed simple enough. This is the 3rd time this week that I've lost substantial time to laziness. I'm pretty pissed to tell the truth and I find myself wrapping things in doseq more and more just to be sure. I rarely use 'for' anymore, what's the point? Here is the code that gave me trouble: (map #(add-watch % watcher callback-fn) all-agents) This was not executing. I had to change it to the below expression: (doseq [agent all-labor-agents] (add-watch agent total-labor-agent callback-fn)) This second expression seems less elegant than the map above. Why doesn't clojure realize that an add-watch really should actually loop over all-agents? Why is it that Java calls are not made in similar expressions? Is laziness so useful that we should waste time investigating and fixing errors like this? Sure, there could be special constructs for laziness when we really need it. However, clojure shouldn't default to it IMO. At this point, laziness is a nice concept but it feels somewhat removed from reality to tell the truth. Of course I want to iterate over my collection when I'm doing an add-watch! What am I missing? Thanks, Max --~--~-~--~~~---~--~~ 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: Simple math functions should support sequences
This is a common misconception: passing a seq to apply doesn't force its evaluation. Ahh, is this because the [ more] portion is itself a lazy sequence? That's very cool =) Hmm, the (reduce + ...) approach works just fine, but if it is already implemented as reduce, it seems like it would be very easy to allow (+) to take a sequence. I still think the ( (range 10)) ... use case is really worthwhile though, and I don't see a way to accomplish it with reduce. Thanks, Stu On Tue, Feb 3, 2009 at 1:36 PM, Christophe Grand christo...@cgrand.netwrote: Hello, stuhood a écrit : Functions like (+), (*), (-), (and probably more) should support sequences as parameters. The current way to accomplish this (without implementing your own sum using reduce) seems to be: (apply + (map #(. Math pow 2 %) (range 10))) ... which has to generate the sequence first. This is a common misconception: passing a seq to apply doesn't force its evaluation. You can test this fact by passing an infinite seq to a function: (defn second-arg [ args] (second args)) user= (apply second-arg (iterate inc 0)) 1 and (apply + some-seq) is really equivalent to (reduce + some-seq), see the def of + in core.clj: (defn + ... ([x y more] (reduce + (+ x y) more))) Christophe -- Professional: http://cgrand.net/ (fr) On Clojure: http://clj-me.blogspot.com/ (en) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com 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: Simple math functions should support sequences
but apply works very well for this use case: (apply (range 10)) and it stops as soon as it can: Alright, I fold... thanks for clearing things up Christophe! On Tue, Feb 3, 2009 at 3:13 PM, Christophe Grand christo...@cgrand.netwrote: Stu Hood a écrit : I still think the ( (range 10)) ... use case is really worthwhile though, and I don't see a way to accomplish it with reduce. reduce is not a good fit since you would want to short circuit the computation at the first false. but apply works very well for this use case: (apply (range 10)) and it stops as soon as it can: user=(apply (map #(doto % println) (concat (range 10 20) (range 10 10 11 12 13 14 15 16 17 18 19 0 false Christophe -- Professional: http://cgrand.net/ (fr) On Clojure: http://clj-me.blogspot.com/ (en) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com 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: Synchronization Benchmarks
I added a Clojure implementation based on an Atom instead of a Ref, and re-ran the tests (this time on a quad core machine). I also fixed the calculation of the percent change in both tests (ugh). It looks like using an Atom is slightly more performant than a Ref if you are making a single state change that is commutative/indempotent. Also, RWDict fell apart on a quad core machine (independent of the number of writes): I'll try with the alternative fairness setting like you suggested. Thanks, Stu On 1/16/09, Christian Vest Hansen karmazi...@gmail.com wrote: Another thing you might want to test is the fairness of the rw-lock in your RWDict, because even a couple of very active readers can easily starve out any number of writers when the rw-lock is non-fair. The reason is simple: readers can interleave but writers cannot, and writers can only get in when noone is reading :) On Fri, Jan 16, 2009 at 4:21 AM, Stu Hood stuh...@gmail.com wrote: Ah! but a mere hash table is not bi-directional :-) Right =) I got the idea in a Channel 9 video about MS' efforts with STM: http://channel9.msdn.com/shows/Going+Deep/Software-Transactional-Memory-The-Current-State-of-the-Art/ (which reminds me, the spin-lock approach they try is probably fairly close to using an Atom in Clojure). I made the changes that Christophe suggested, and added type hints for the HashMaps used in CLJDict, and the speed improvement is very impressive. To see the scalability of the different approaches, I graphed with various numbers of threads and read percentages: http://github.com/stuhood/clojure-conc/tree/master/results Two conclusions: 1. The overhead for STM with low contention is very reasonable, 2. Optimism + MVCC + persistence fall down when faced with a majority of writes. (see the 100% write case in the writes graph.) Thanks, Stu On Thu, Jan 15, 2009 at 2:52 PM, Christian Vest Hansen karmazi...@gmail.com wrote: On Thu, Jan 15, 2009 at 8:47 PM, Christian Vest Hansen karmazi...@gmail.com wrote: On Thu, Jan 15, 2009 at 8:35 PM, Mark H. mark.hoem...@gmail.com wrote: On Jan 15, 1:38 am, stuhood stuh...@gmail.com wrote: The benchmark contains 4 bi-directional dictionary implementations: ... Doesn't Java already have a more optimized thread-safe hash table that works by locking individual buckets, rather than the whole table? Maybe I'm just confused ;-P Ah! but a mere hash table is not bi-directional :-) -- Venlig hilsen / Kind regards, Christian Vest Hansen. -- 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: Synchronization Benchmarks
Ah! but a mere hash table is not bi-directional :-) Right =) I got the idea in a Channel 9 video about MS' efforts with STM: http://channel9.msdn.com/shows/Going+Deep/Software-Transactional-Memory-The-Current-State-of-the-Art/(which reminds me, the spin-lock approach they try is probably fairly close to using an Atom in Clojure). I made the changes that Christophe suggested, and added type hints for the HashMaps used in CLJDict, and the speed improvement is very impressive. To see the scalability of the different approaches, I graphed with various numbers of threads and read percentages: http://github.com/stuhood/clojure-conc/tree/master/results Two conclusions: 1. The overhead for STM with low contention is very reasonable, 2. Optimism + MVCC + persistence fall down when faced with a majority of writes. (see the 100% write case in the writes graph.) Thanks, Stu On Thu, Jan 15, 2009 at 2:52 PM, Christian Vest Hansen karmazi...@gmail.com wrote: On Thu, Jan 15, 2009 at 8:47 PM, Christian Vest Hansen karmazi...@gmail.com wrote: On Thu, Jan 15, 2009 at 8:35 PM, Mark H. mark.hoem...@gmail.com wrote: On Jan 15, 1:38 am, stuhood stuh...@gmail.com wrote: The benchmark contains 4 bi-directional dictionary implementations: ... Doesn't Java already have a more optimized thread-safe hash table that works by locking individual buckets, rather than the whole table? Maybe I'm just confused ;-P Ah! but a mere hash table is not bi-directional :-) -- 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: test-is reporting problem
You do that. -another Stuart On Thu, Jan 15, 2009 at 10:32 PM, Stuart Sierra the.stuart.sie...@gmail.com wrote: I was afraid that would happen. I'll fix it, probably tomorrow. -the other Stuart On Jan 15, 6:27 pm, Stuart Halloway stuart.hallo...@gmail.com wrote: The improved error reposting in test-is breaks some tests, e.g. from the book: (deftest test-lazy-index-of-any-with-match (is (with-out-str (is (zero? (index-of-any zzabyycdxx #{\z \a} Iterating overz\n) (is (with-out-str (is (= 3 (index-of-any zzabyycdxx #{\b \y} Iterating overz\nIterating over z\nIterating over a\n)) The problem is that it tries to take the value of with-out-str, not realizing that it is a macro. Should I (1) rewrite the test to not use a macro? (2) take a stab at fixing this in test-is? (3) get out of the way and let another Stuart handle it? :-) 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 -~--~~~~--~~--~--~---