Re: adding a member to a set in a map in a map in a map in a ref
Hi, Am 05.07.2009 um 07:27 schrieb Rowdy Rednose: user=> (dosync (alter gnu-rms update-in [:key1 :key2 :key3] #(conj % "foo"))) {:key1 {:key2 {:key3 #{"foo" You actually don't need the anonymous function... (dosync (alter gnu-rms update-in [:key1 :key2 :key3] conj "foo")) Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: loneclojurian at ICFP programming contest
Hello, Thanks to Rich's advices, I managed to make your ICFP program run very fast. I have made a few modifications: - changed the code following Rich's advices in order to have primitive array access everywhere. - I didn't managed to do it for booleans, so I used a java object conataining only a public boolean for StatusReg. - The biggest speep-up was the chunking of the generated program. It seems that the fact that the program was so big prevented the JIT to compile it. So I changed the code to emit it by chunk of around 50 guest VM instructions. (after a few tries, it seemed this was a good figure. On my computer, the performance seems to be highly sensitive on the size of the chunk. I don't really understand why and it worries me a bit on the correctness of my program. ) To do so, I create intermediate local functions that I call. - I generate the program at compile time, in order to only mesure execution time and not compilation time. After, when I run the benchmark in -server with a big enough CacheCode area (1000m), and enough iterations to have everything JITed, I get more than 860.000 iterations per second. (I benchmarked 100 000 000 iterations in 121 sec, on my 2.4GHz computer). When you look at the profile, 98.7% is spent in compiled code, 1.3% in interpreted and 0% in stub. This proves that input program actually get translated to Clojure, compiled to byte code, recompiled to native instructions and then executed natively. This is so fast, that I actually wonder whether too many things get optimized away and the program is not benchmarking anything anymore. Or maybe my code transformation is completly wrong and throws everything away. igorrumiha, I am going to send you the source in a private mail so you can check whether the program still works, and put it in your git hub if it does. (I don't know what is the policy of this list regarding attaching files.) If it does work, and I have not made some stupid mistakes, is is a nice example of program where Clojure's performance can compete with C and even outperform it, because you can write easily a better implementation. (The code I wrote is really ugly, because it was made as multiple hacks, but I think with more experience than me and more cleverness in the design, you can keep the code really expressive and clear, while achieving the same level of performance.). Best, Nicolas. --~--~-~--~~~---~--~~ 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: adding a member to a set in a map in a map in a map in a ref
You're right, the scenario that I described doesn't need it. In my actual code I need it because the function actually reads #(conj (or % #{}) constraint#) If I don't do that, I get a list instead of a set. On Jul 5, 5:12 pm, Meikel Brandmeyer wrote: > Hi, > > Am 05.07.2009 um 07:27 schrieb Rowdy Rednose: > > > user=> (dosync (alter gnu-rms update-in [:key1 :key2 :key3] #(conj % > > "foo"))) > > > {:key1 {:key2 {:key3 #{"foo" > > You actually don't need the anonymous function... > > (dosync > (alter gnu-rms update-in [:key1 :key2 :key3] conj "foo")) > > Sincerely > Meikel > > smime.p7s > 2KViewDownload --~--~-~--~~~---~--~~ 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: loneclojurian at ICFP programming contest
On Jul 5, 2:31 am, Nicolas Oury wrote: > After, when I run the benchmark in -server with a big enough CacheCode area > (1000m), and enough iterations to have everything JITed, I get more than > 860.000 iterations per second. (I benchmarked 100 000 000 iterations in 121 > sec, on my 2.4GHz computer). That's 3000 clock cycles per VM instruction? I'm not very familiar with the problem, but I thought "straight" C bytecode interpreters were at around 30 and compiling the VM code to native code (with JIT) reduced it to 7. Is this right? --~--~-~--~~~---~--~~ 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: conversation with Corey Haines
Interesting talk Stuart, thanks for the link. On Jul 4, 1:12 pm, Stuart Halloway wrote: > Corey Haines, the touring software journeyman, recently spent a few > days at Relevance (including a day pairing on a Clojure project). At > the end, he videoed a conversation with me [1]. In Part 2 of the video > we talk about Clojure. > > The conversation does not go at all deep technically, but if you need > something to show your manager that real people are using Clojure you > might find it interesting. > > [1]http://programmingtour.blogspot.com/2009/07/conversation-with-stuart-... --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Adding type hint causes compiler error
Hi, The following code works as expected: (import 'javax.imageio.ImageIO 'java.io.File 'java.awt.image.BufferedImage) (defn bi-get-pixels [bi] (vec (.. bi (getData) (getPixels 0 0 (.getWidth bi) (.getHeight bi) nil (bi-get-pixels (. ImageIO read (File. "/home/phil/prog/small- test.png"))) But if *warn-on-reflection* is true, it generates four warnings. If we try to shut it up with a type hint: (defn bi-get-pixels [#^BufferedImage bi] (vec (.. bi (getData) (getPixels 0 0 (.getWidth bi) (.getHeight bi) nil Exception in thread "main" java.lang.IllegalArgumentException: More than one matching method found: getPixels (imagio-test.clj:7) at clojure.lang.Compiler.analyzeSeq(Compiler.java:4558) ... Caused by: java.lang.IllegalArgumentException: More than one matching method found: getPixels at clojure.lang.Compiler.getMatchingParams(Compiler.java:2122) at clojure.lang.Compiler$InstanceMethodExpr. (Compiler.java:1159) at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java: 810) at clojure.lang.Compiler.analyzeSeq(Compiler.java:4551) ... 34 more The problem here is that getPixels has three forms: ( http://java.sun.com/j2se/1.4.2/docs/api/java/awt/image/Raster.html ) double[] getPixels(int x, int y, int w, int h, double[] dArray) Returns a double array containing all samples for a rectangle of pixels, one sample per array element. float[]getPixels(int x, int y, int w, int h, float[] fArray) Returns a float array containing all samples for a rectangle of pixels, one sample per array element. int[] getPixels(int x, int y, int w, int h, int[] iArray) Returns an int array containing all samples for a rectangle of pixels, one sample per array element. In each case, if the final argument is NULL it is ignored, and if not the array is populated with the return data from the call (generating an error if it's not large enough). Is it possible to specify which invocation of getPixels I intend without passing an array? I've tried putting #^ints in some likely- looking places, but nil can't be type-hinted and the others seem to have no effect. I've also tried splitting the .. up: (defn bi-get-pixels [#^BufferedImage bi] (let [rast (.getData bi) #^ints pi (.getPixels rast 0 0 (.getWidth bi) (.getHeight bi) nil)] pi)) But this doesn't work either. I could do manual reflection on Raster to get the correct method and .invoke it, but that seems far more complicated than necessary. Any other ideas? -Phil --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Mysterious ClassFormatError after simple code change.
I had this: (defn- subexpressions-of-sum** [[n p] terms] (let-print [sum (cons '+ (map #(factor-term % n p) terms)) prod (rest (make-product* n p))] (concat [sum] (subexpressions-of-product (cons sum prod) in a source file with other definitions. Load-file worked. I then changed it to this: (defn- subexpressions-of-sum** [[n p] terms] (let-print [sum (cons '+ (map #(factor-term % n p) terms)) prod (rest (make-product* n p))] (cons sum (map #(cons '* (cons sum (rest %))) (concat prod (subexpressions-of-product prod)) and got: # when I tried to do a load-file. That function definition was the ONLY thing I changed, but I'm at a loss to find any kind of error in it. Delimiters balance, all of the referenced functions exist, basically there's nothing wrong. The full exception trace, which required evaluating (.printStackTrace (.getCause *e)) at the repl, is: java.lang.ClassFormatError: Unknown constant tag 32 in class file com/mycompany/myfile$eval__14598 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:621) at java.lang.ClassLoader.defineClass(ClassLoader.java:466) at clojure.lang.DynamicClassLoader.defineClass(DynamicClassLoader.java:42) at clojure.lang.Compiler$FnExpr.getCompiledClass(Compiler.java:3417) at clojure.lang.Compiler$FnExpr.eval(Compiler.java:3428) at clojure.lang.Compiler.eval(Compiler.java:4531) at clojure.core$eval__3990.invoke(core.clj:1728) at clojure.main$repl__5813$read_eval_print__5825.invoke(main.clj:176) at clojure.main$repl__5813.doInvoke(main.clj:193) at clojure.lang.RestFn.invoke(RestFn.java:548) at org.enclojure.repl.main$create_clojure_repl__53$repl_thread_fn__55.invoke(main.clj:96) at clojure.lang.AFn.run(AFn.java:37) at java.lang.Thread.run(Thread.java:619) It does not point to any line of my source file. Perhaps the rewritten version of the function provokes a compiler bug? If there is a known bug that would cause this, let me know of the known workaround. If there is an error in the second version of my function, let me know. (It has intentionally different semantics from the first version, so that's not an error in and of itself.) --~--~-~--~~~---~--~~ 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: loneclojurian at ICFP programming contest
Each iteration contains 266 instructions. So, it is more like 10.5 clock cycle per instructions. Probably the cost of the method call, that I had to introduce in order to have the JIT compile, or the fact that the status register is not directly in a local variable but with an indirection, because we can't set the value of a local variable directly. I could improve that by threading the status reg as a local parameter with let instructions, but that would mean change a lot of things in the code... And I got lazy. If the program is correct, of which I am not sure yet, it is already quite good as it is quite straightforward and probably far more readable/maintanable than the implementations in other languages. Moreover, Clojure is young and being so close from the best solution would already be great. Actually, that would be so good, that I actually think there is a mistake somewhere either in my program or my computation of the speed. Let's wait for igorrumiha to check and to test this implementation. Best regards, Nicolas. On Sun, Jul 5, 2009 at 12:18 PM, fft1976 wrote: > > On Jul 5, 2:31 am, Nicolas Oury wrote: > > > After, when I run the benchmark in -server with a big enough CacheCode > area > > (1000m), and enough iterations to have everything JITed, I get more than > > 860.000 iterations per second. (I benchmarked 100 000 000 iterations in > 121 > > sec, on my 2.4GHz computer). > > That's 3000 clock cycles per VM instruction? I'm not very familiar > with the problem, but I thought "straight" C bytecode interpreters > were at around 30 and compiling the VM code to native code (with JIT) > reduced it to 7. Is this right? > > > > --~--~-~--~~~---~--~~ 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: print-base / print-radix?
Parth, I've created a little wrapper as promised at: http://gist.github.com/141001. It gives you my-pprint: user> (binding [*print-base* 2] (my-pprint (range 10))) (0 1 10 11 100 101 110 111 1000 1001) nil user> While doing this, I realized to my horror that ~r doesn't do 0 correctly for non-standard bases. I'll fix that soon. Also, I've started to implement *print-radix* and *print-base* for real in cl-format and the pretty printer, so those should be available soon. Enjoy, Tom On Jul 3, 3:16 am, Parth wrote: > On Jul 3, 11:25 am, Tom Faulhaber wrote: > > > Parth, > > > I was thinking about this a little more today and I came up with a way > > to extend the pretty printer easily to support *print-radix* with a > > little wrapper. I'll try to get a chance to write it up for you > > tomorrow. > > > Tom > > Sounds perfect. Thanks very much :) > > Regards, > Parth > > > On Jul 2, 6:29 pm, Parth wrote: > > > > On Jul 3, 6:15 am, Parth wrote: > > > > > Tom, Chouser, Thanks for your responses. > > > > > As of now I am doing the same thing as suggested. > > > > However, this tends be become painful the moment structures > > > > start to nest. For e.g. I am using Clojure to decode a bit > > > > of assembly and below is what I end up doing to see the > > > > values of interest in hex: > > > > > user=> (decode :b32 (nth test-ops 3)) > > > > {:inst {:prefix (), :code (199 69 248 10 0 0 0), :op :movl, :args > > > > [{:type :Ev-mem, :arg {:reg :ebp, :disp -8}} 10]}, :more ()} > > > > user=> (def r (decode :b32 (nth test-ops 3))) > > > > #'user/r > > > > user=> (map hex (get-in r [:inst :code])) > > > > ("c7" "45" "f8" "a" "0" "0" "0") > > > > user=> (hex (second (get-in r [:inst :args]))) > > > > "a" > > > > user=> > > > > > Basically, I need to extract each number seq or value > > > > individually and print it in hex for every instruction I > > > > decode and view. > > > > > This isn't too much fun to do in the middle of a debug session :) > > > > > Having something like *print-base* would be ideal IMHO > > > > would make scenarios like this really easy as one could > > > > simply do: > > > > > user=> (set! *print-base* 16) > > > > user=> (decode :b32 (nth test-ops 3)) > > > > {:inst {:prefix (), :code (c7 47 f8 a 0 0 0), :op :movl, :args > > > > [{:type :Ev-mem, :arg {:reg :ebp, :disp f8}} a]}, :more ()} > > > > > In the absence of this I thought of writing a function > > > > that would take an arbitrary Clojure structure/coll and print > > > > it out in the manner like above. But then it won't > > > > be much different from pprint with radix support but without > > > > the pretty part. > > > > > I suppose what I am hoping is that a feature request for > > > > *print-base* sort of a mechanism get considered > > > > for Clojure as it makes scenarios like the above very > > > > easy to deal with. Any chance of this being somewhere > > > > on the Clojue todo? :) > > > > Rich, > > > > If this is something you think would be a good addition > > > to Clojure I could give a shot at creating a patch for > > > this (with a CA of course). Please let me know. > > > > I think rather than a generic radix support, if > > > we have hex, bin and octal supported, most uses > > > cases should be covered. > > > > Regards, > > > Parth > > > > > I will probably create a poor mans radix based print > > > > in the mean time for the this scenario. That should > > > > be an interesting exercise. > > > > > Thanks, > > > > Parth > > > > > On Jul 2, 10:58 pm, Chouser wrote: > > > > > > On Thu, Jul 2, 2009 at 4:51 AM, Parth > > > > > > Malwankar wrote: > > > > > > > I frequently deal with hex and binary numbers. > > > > > > As of now when I need to view a list of numbers > > > > > > I just map a little hex function to it to translate it > > > > > > into a list of hex strings at the repl. > > > > > > > Having something like *print-base* / *print-radix* [1] may be > > > > > > valuable in such a scenario > > > > > > I don't think Java's built-in formatter is nearly as > > > > > flexible as those, but getting hex or octal strings is easy > > > > > enough: > > > > > > user=> (format "%d" 255) > > > > > "255" > > > > > user=> (format "%o" 255) > > > > > "377" > > > > > user=> (format "%x" 255) > > > > > "ff" > > > > > user=> (format "%X" 255) > > > > > "FF" > > > > > > --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 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: loneclojurian at ICFP programming contest
On Jul 5, 3:05 pm, Nicolas Oury wrote: > Actually, that would be so good, that I actually think there is a mistake > somewhere either in my program or my computation of the speed. > Let's wait for igorrumiha to check and to test this implementation. > OK, I did my tests, I found and fixed two small bugs and as far as I can tell the VM is now working correctly. I couldn't, however, reproduce the timings Nicolas had, on my machine (a 2 Ghz MacBook with java 1.6 build 1.6.0_13-b03-211) I got timings between 570 and 637 seconds for 100 000 000 executions. So, this translates, on average, to 163585 executions/second. That translates to 45.9 clock cycles per guest VM instruction. I used these tuning options for the Java VM: -XX:InitialCodeCacheSize=768m -XX:ReservedCodeCacheSize=1024m -Xms768M -Xmx768M -server I consider this an excellent result, about 2.5 times faster than my simple Java implementation of the VM. I can't explain the 5.2x difference between my and Nicolas' timings, though :) What I can say is that my quest for Orbital Virtual Machine speed is satisfied. With a simulation time limit of 3 million seconds (set by the contest rules) this VM now reaches that limit in ~19 seconds of wallclock time. That's even good enough for interactive exploration of problem solutions (I think it's very likely that it will usually take more than 19 seconds to write a new version of a solution and then run it in the REPL :)) I think it's safe to say that once again it's proved that Clojure easily matches the Java level of performance. What I've learned from this is: 1. I need to read the documentation more carefully :), 2. I need to learn how to write macros, 3. I need to get myself acquainted with the underlying JVM platform, 4. When in trouble, the clojure group is an excellent place to get help. 5. Write lots and lots of Clojure code, that is the only way to get enough experience for the next ICFP contest :) Thanks a bunch everyone, especially Nicolas for being so persistent :) p.s. I'll update my git repo in a day or two, I need to clean up the code a bit and port the game logic code to use the new VM. Igor. --~--~-~--~~~---~--~~ 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: ants.clj and render thread starvation
On Tue, Jun 30, 2009 at 18:01, Rich Hickey wrote: > > On Tue, Jun 30, 2009 at 7:50 AM, Krukow wrote: >> >> On Jun 29, 7:51 pm, B Smith-Mannschott wrote: >> [snip...] >>> much on my netbook. The problem seems to be that with only a single >>> (hyperthreaded) core the render agent is almost constantly interrupted >>> by some pesky ant while attempting to snapshot the world, forcing the >>> render agent to automatically retry. And so, the ants run merrily >>> around the world, only I can't see it. >> >> If my understanding of the STM is correct (and it may very well not >> be) the render function should not retry. The render function reads >> all the refs that define ant positions, but does not modify any ref. >> So I suspect that the missing renders are caused by a thread >> starvation rather than retries. >> >> But I'd like to hear if Rich agrees ;-) >> > > MVCC history in Clojure's STM is dynamic, created by need. There is no > read tracking, and more important for this case, no transaction > tracking. So, if a read transaction is unable to satisfy its snapshot > view from history, it will flag the offending ref with a fault and > retry. When a writer sees a ref with a read fault it will grow history > for that ref. In this way only as much history is created as is needed > to satisfy the dynamic contention patterns, and > tracking/synchronization is minimized. > > The problem for scanning readers like render is that the ref that > caused the fault this pass is unlikely to be the ref that causes the > fault next time, and it will take a while to accumulate even one step > of history for each scanned ref using the fault system. > > This has caused me to implement (in git master) some long-planned > controls on ref history. You can now supply :min-history and > :max-history args to ref. The defaults are 0 and 10 respectively. By > setting min-history to some positive value, history will be > accumulated even in the absence of faults, providing a window, if you > will, for scanning readers like render. > > You can see this history acquisition by periodically running: > > (map ref-history-count (world 20)) > > while the ants demo is going. > > So, now you can preemptively maintain history in the ants demo by > modifying the world init with some min-history (the value 2 below is > your 'knob' for accommodating the duration of the render sweep) > > (def world ... (ref (struct cell 0 0) :min-history 2) ...) > > Please let me know how that works for you, and, everyone else, please > let me know if max-history default of 10 causes you any trouble > ("Transaction failed after reaching retry limit"). Sorry it took me so long to try this out... I've tried this with a build of a1397390d8b3b63f2039359520629d87b152d717 (July 4), I tried :min-history values of 2 and 9, which didn't help, meaning the window stayed blank because the rendering agent does not run to completion. I was able to get something to display by dialing :min-history up to 100. It draws less than one frame per second, but it does draw. (Perhaps it's too much to expect for a single core to juggle some 50 threads.) I'm going to play around with it some more and see what I find. // Ben --~--~-~--~~~---~--~~ 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: ants.clj and render thread starvation
I'm on an hp mini. It runs on an Atom processor. I ran ants.clj and it was frozen for a little while. Then after maybe 30 seconds it looked normal -- a tick every second or half second or so. I'm running a lot of applications though. On Ubuntu here too. On Sun, Jul 5, 2009 at 11:17 PM, B Smith-Mannschott wrote: > > On Tue, Jun 30, 2009 at 18:01, Rich Hickey wrote: > > > > On Tue, Jun 30, 2009 at 7:50 AM, Krukow wrote: > >> > >> On Jun 29, 7:51 pm, B Smith-Mannschott wrote: > >> [snip...] > >>> much on my netbook. The problem seems to be that with only a single > >>> (hyperthreaded) core the render agent is almost constantly interrupted > >>> by some pesky ant while attempting to snapshot the world, forcing the > >>> render agent to automatically retry. And so, the ants run merrily > >>> around the world, only I can't see it. > >> > >> If my understanding of the STM is correct (and it may very well not > >> be) the render function should not retry. The render function reads > >> all the refs that define ant positions, but does not modify any ref. > >> So I suspect that the missing renders are caused by a thread > >> starvation rather than retries. > >> > >> But I'd like to hear if Rich agrees ;-) > >> > > > > MVCC history in Clojure's STM is dynamic, created by need. There is no > > read tracking, and more important for this case, no transaction > > tracking. So, if a read transaction is unable to satisfy its snapshot > > view from history, it will flag the offending ref with a fault and > > retry. When a writer sees a ref with a read fault it will grow history > > for that ref. In this way only as much history is created as is needed > > to satisfy the dynamic contention patterns, and > > tracking/synchronization is minimized. > > > > The problem for scanning readers like render is that the ref that > > caused the fault this pass is unlikely to be the ref that causes the > > fault next time, and it will take a while to accumulate even one step > > of history for each scanned ref using the fault system. > > > > This has caused me to implement (in git master) some long-planned > > controls on ref history. You can now supply :min-history and > > :max-history args to ref. The defaults are 0 and 10 respectively. By > > setting min-history to some positive value, history will be > > accumulated even in the absence of faults, providing a window, if you > > will, for scanning readers like render. > > > > You can see this history acquisition by periodically running: > > > > (map ref-history-count (world 20)) > > > > while the ants demo is going. > > > > So, now you can preemptively maintain history in the ants demo by > > modifying the world init with some min-history (the value 2 below is > > your 'knob' for accommodating the duration of the render sweep) > > > > (def world ... (ref (struct cell 0 0) :min-history 2) ...) > > > > Please let me know how that works for you, and, everyone else, please > > let me know if max-history default of 10 causes you any trouble > > ("Transaction failed after reaching retry limit"). > > Sorry it took me so long to try this out... > > I've tried this with a build of > a1397390d8b3b63f2039359520629d87b152d717 (July 4), I tried > :min-history values of 2 and 9, which didn't help, meaning the window > stayed blank because the rendering agent does not run to completion. I > was able to get something to display by dialing :min-history up to > 100. It draws less than one frame per second, but it does draw. > (Perhaps it's too much to expect for a single core to juggle some 50 > threads.) > > I'm going to play around with it some more and see what I find. > > // Ben > > > > -- John --~--~-~--~~~---~--~~ 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: loneclojurian at ICFP programming contest
I don't know if it will help, but I used another flag. I have not my computer at hand but I think it was in the lines of -XX agressiveoptimizations. Moreover, the performance goes from 200 000 to 800 000 depending on the size of the chunks. I tried to launch for 1 or 10 millions iterations to find the fastest on my computer. That is quite strange the fact that the size xhange so much the result. Really a fun exercize in writing benchmarking clojure, though. Best, Nicolas. On Jul 5, 2009 6:53 PM, "igorrumiha" wrote: On Jul 5, 3:05 pm, Nicolas Oury wrote: > Actually, that would be so good, ... OK, I did my tests, I found and fixed two small bugs and as far as I can tell the VM is now working correctly. I couldn't, however, reproduce the timings Nicolas had, on my machine (a 2 Ghz MacBook with java 1.6 build 1.6.0_13-b03-211) I got timings between 570 and 637 seconds for 100 000 000 executions. So, this translates, on average, to 163585 executions/second. That translates to 45.9 clock cycles per guest VM instruction. I used these tuning options for the Java VM: -XX:InitialCodeCacheSize=768m -XX:ReservedCodeCacheSize=1024m -Xms768M -Xmx768M -server I consider this an excellent result, about 2.5 times faster than my simple Java implementation of the VM. I can't explain the 5.2x difference between my and Nicolas' timings, though :) What I can say is that my quest for Orbital Virtual Machine speed is satisfied. With a simulation time limit of 3 million seconds (set by the contest rules) this VM now reaches that limit in ~19 seconds of wallclock time. That's even good enough for interactive exploration of problem solutions (I think it's very likely that it will usually take more than 19 seconds to write a new version of a solution and then run it in the REPL :)) I think it's safe to say that once again it's proved that Clojure easily matches the Java level of performance. What I've learned from this is: 1. I need to read the documentation more carefully :), 2. I need to learn how to write macros, 3. I need to get myself acquainted with the underlying JVM platform, 4. When in trouble, the clojure group is an excellent place to get help. 5. Write lots and lots of Clojure code, that is the only way to get enough experience for the next ICFP contest :) Thanks a bunch everyone, especially Nicolas for being so persistent :) p.s. I'll update my git repo in a day or two, I need to clean up the code a bit and port the game logic code to use the new VM. Igor. --~--~-~--~~~---~--~~ You received this message because you are subs... --~--~-~--~~~---~--~~ 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: Mysterious ClassFormatError after simple code change.
On Jul 5, 2009, at 2:01 AM, John Harrop wrote: and got: #32 in class file com/mycompany/myfile$eval__14598 (NO_SOURCE_FILE:0)> Are there large literals elsewhere in the same namespace? Here's some info from a previous report of this error: http://groups.google.com/group/clojure/browse_frm/thread/e556434a382de814/f8183c88db8fa257?lnk=gst&q=oct+18+2008#f8183c88db8fa257 --Steve smime.p7s Description: S/MIME cryptographic signature
Re: ANN: FnParse, a functional parsing library
If you need a JSON parser, there's already a good one included with clojure.contrib. The one with the FnParse library is just a sample to show how it works. But please feel free to use it however it can be useful to you. :) On Jul 4, 1:45 pm, Wilson MacGyver wrote: > Very timely, I need to parse a bunch on JSON files on Monday :) good > work > > Sent from my iPhone > > On Jul 4, 2009, at 3:16 PM, samppi wrote: > > > > > > > I'm pleased to announce FnParse, a monadic functional parsing library > > for Clojure, half a year in the making. I started on FnParse in > > December as my first Clojure project, and now it has matured to > > something that I believe is very and immediately useful. Currently, > > I'm writing a YAML parser using FnParse. > > > With FnParse, you can easily parse a string or any sequence of tokens > > into native data structures. FnParse is based on the concept of the > > rule, a self-contained function that accepts a state data structure, > > containing a sequence of tokens, and either consumes some tokens-- > > turning them into new data--or fails. Rules correspond nicely to EBNF > > productions and productions in other sort of grammars. FnParse > > provides common rules, functions that create new rules, and functions > > that facilitate using rules. > > > A sample JSON parser is > > athttp://wiki.github.com/joshua-choi/fnparse/sample-json-parser > > . > > Online documentation is available > > at:http://wiki.github.com/joshua-choi/fnparse > > . > > The source is at:http://github.com/joshua-choi/fnparse. > > > If you are confused about anything or find any bugs, please create an > > issue on GitHub (http://github.com/joshua-choi/fnparse/issues) or send > > me a message on GitHub. --~--~-~--~~~---~--~~ 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: Adding type hint causes compiler error
Hi Phil, Part of me hopes there's a nicer way of doing this, but I was able to get it working using: (defn bi-get-pixels [#^BufferedImage bi] (let [raster (.getData bi) pixels (.getPixels raster 0 0 (.getWidth bi) (.getHeight bi) (cast (Class/forName "[I") nil))] (vec pixels))) Cheers, Mark On Jul 5, 10:18 pm, "philip.hazel...@gmail.com" wrote: > Hi, > > The following code works as expected: > > (import 'javax.imageio.ImageIO 'java.io.File > 'java.awt.image.BufferedImage) > (defn bi-get-pixels > [bi] > (vec (.. bi (getData) (getPixels 0 0 (.getWidth bi) (.getHeight bi) > nil > (bi-get-pixels (. ImageIO read (File. "/home/phil/prog/small- > test.png"))) > > But if *warn-on-reflection* is true, it generates four warnings. If we > try to shut it up with a type hint: > > (defn bi-get-pixels > [#^BufferedImage bi] > (vec (.. bi (getData) (getPixels 0 0 (.getWidth bi) (.getHeight bi) > nil > > Exception in thread "main" java.lang.IllegalArgumentException: More > than one matching method found: getPixels (imagio-test.clj:7) > at clojure.lang.Compiler.analyzeSeq(Compiler.java:4558) > ... > Caused by: java.lang.IllegalArgumentException: More than one matching > method found: getPixels > at clojure.lang.Compiler.getMatchingParams(Compiler.java:2122) > at clojure.lang.Compiler$InstanceMethodExpr. > (Compiler.java:1159) > at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java: > 810) > at clojure.lang.Compiler.analyzeSeq(Compiler.java:4551) > ... 34 more > > The problem here is that getPixels has three forms: > (http://java.sun.com/j2se/1.4.2/docs/api/java/awt/image/Raster.html) > double[] getPixels(int x, int y, int w, int h, double[] dArray) > Returns a double array containing all samples for a > rectangle of pixels, one sample per array element. > float[] getPixels(int x, int y, int w, int h, float[] fArray) > Returns a float array containing all samples for a rectangle > of pixels, one sample per array element. > int[] getPixels(int x, int y, int w, int h, int[] iArray) > Returns an int array containing all samples for a rectangle > of pixels, one sample per array element. > > In each case, if the final argument is NULL it is ignored, and if not > the array is populated with the return data from the call (generating > an error if it's not large enough). > > Is it possible to specify which invocation of getPixels I intend > without passing an array? I've tried putting #^ints in some likely- > looking places, but nil can't be type-hinted and the others seem to > have no effect. I've also tried splitting the .. up: > > (defn bi-get-pixels > [#^BufferedImage bi] > (let [rast (.getData bi) > #^ints pi (.getPixels rast 0 0 (.getWidth bi) (.getHeight bi) nil)] > pi)) > > But this doesn't work either. I could do manual reflection on Raster > to get the correct method and .invoke it, but that seems far more > complicated than necessary. Any other ideas? > > -Phil --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Adding type hint causes compiler error
On Sun, Jul 5, 2009 at 5:18 AM, philip.hazel...@gmail.com wrote: > > Hi, > > The following code works as expected: > > (import 'javax.imageio.ImageIO 'java.io.File > 'java.awt.image.BufferedImage) > (defn bi-get-pixels > [bi] > (vec (.. bi (getData) (getPixels 0 0 (.getWidth bi) (.getHeight bi) > nil > (bi-get-pixels (. ImageIO read (File. "/home/phil/prog/small- > test.png"))) > > But if *warn-on-reflection* is true, it generates four warnings. If we > try to shut it up with a type hint: > > (defn bi-get-pixels > [#^BufferedImage bi] > (vec (.. bi (getData) (getPixels 0 0 (.getWidth bi) (.getHeight bi) > nil > > Exception in thread "main" java.lang.IllegalArgumentException: More > than one matching method found: getPixels (imagio-test.clj:7) > at clojure.lang.Compiler.analyzeSeq(Compiler.java:4558) > ... > Caused by: java.lang.IllegalArgumentException: More than one matching > method found: getPixels > at clojure.lang.Compiler.getMatchingParams(Compiler.java:2122) > at clojure.lang.Compiler$InstanceMethodExpr. > (Compiler.java:1159) > at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java: > 810) > at clojure.lang.Compiler.analyzeSeq(Compiler.java:4551) > ... 34 more > > The problem here is that getPixels has three forms: ( > http://java.sun.com/j2se/1.4.2/docs/api/java/awt/image/Raster.html ) > double[] getPixels(int x, int y, int w, int h, double[] dArray) > Returns a double array containing all samples for a > rectangle of pixels, one sample per array element. > float[] getPixels(int x, int y, int w, int h, float[] fArray) > Returns a float array containing all samples for a rectangle > of pixels, one sample per array element. > int[] getPixels(int x, int y, int w, int h, int[] iArray) > Returns an int array containing all samples for a rectangle > of pixels, one sample per array element. > > In each case, if the final argument is NULL it is ignored, and if not > the array is populated with the return data from the call (generating > an error if it's not large enough). > > Is it possible to specify which invocation of getPixels I intend > without passing an array? I've tried putting #^ints in some likely- > looking places, but nil can't be type-hinted and the others seem to > have no effect. I've also tried splitting the .. up: > > (defn bi-get-pixels > [#^BufferedImage bi] > (let [rast (.getData bi) > #^ints pi (.getPixels rast 0 0 (.getWidth bi) (.getHeight bi) nil)] > pi)) you change (.getPixels rast 0 0 (.getWidth bi) (.getHeight bi) nil) to something like (.getPixels rast (int 0) (int 0) (.getWidth bi) (.getHeight bi) nil) > > But this doesn't work either. I could do manual reflection on Raster > to get the correct method and .invoke it, but that seems far more > complicated than necessary. Any other ideas? > > -Phil > > > -- And what is good, Phaedrus, And what is not good— Need we ask anyone to tell us these things? --~--~-~--~~~---~--~~ 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: loneclojurian at ICFP programming contest
On Jul 5, 10:53 am, igorrumiha wrote: > I think it's safe to say that once again it's proved that Clojure > easily matches the Java level of performance. I think one shouldn't generalize from one [unverified] example. Personally, I'll wait for Jon Harrop or someone to port the relevant Shootout benchmarks or his "Ray tracing" benchmark to Clojure and see what time they get and what the code looks like. For example, some people claim that Haskell is as fast as C, while also being very high-level, but when you look at the Shootout, you'll see that it's BS: they are doing pointer arithmetic in Haskell, for Christ's sake! --~--~-~--~~~---~--~~ 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: Mysterious ClassFormatError after simple code change.
I'm not doing any funny things with load-string. The largest literal at this time is [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997] and has been in there a while without causing problems. The function definition in my original post is the ONLY change between working and not-working. With the first version, the file loads consistently. With the second version, it fails consistently. The error is definitely in that function and not elsewhere, or else it is in the implementation of load-file, the compiler, or even Java or the JVM. The JVM is 1.6.0_something, I forget what. It's pretty current. The literal generated in the post you linked to took a list of four items and doubled it up 13 times, for a grand total of 2^15 = 32768 items. There's nothing that large in that function, nor anything in the second version of it that would expand (say, via a macro) into something that large from a number being changed. This is frankly quite baffling. The changes to the function are innocent from a large-literal or pretty much any other perspective. On 7/5/09, Stephen C. Gilardi wrote: > On Jul 5, 2009, at 2:01 AM, John Harrop wrote: > >> and got: >> >> #> 32 in class file com/mycompany/myfile$eval__14598 (NO_SOURCE_FILE:0)> > > Are there large literals elsewhere in the same namespace? > > Here's some info from a previous report of this error: > > http://groups.google.com/group/clojure/browse_frm/thread/e556434a382de814/f8183c88db8fa257?lnk=gst&q=oct+18+2008#f8183c88db8fa257 > > --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 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 -~--~~~~--~~--~--~---
sanity check needed
I wrote some fairly simple code to demonstrate use of StructMaps and Refs. It's 80 lines including comments. I'd appreciate it if someone could look it over and let me know if I've done anything that isn't very idiomatic. The program models sports teams and players. The main functionality is the ability to trade sets of players between teams. Both teams and players are held by Refs. Players have a reference to their team. Teams have references to their players. The output from the code follows: Before trade: Oilers roster: Wayne Gretzky Mike Krushelnyski Marty McSorley Kings roster: Jimmy Carson Martin Gelinas After trade: Oilers roster: Martin Gelinas Jimmy Carson Kings roster: Wayne Gretzky Mike Krushelnyski Marty McSorley Here's the code: ; A player knows his team, if any. (defstruct player-struct :name :team-ref) ; A team knows its players. (defstruct team-struct :name :player-refs) ; Makes a new Ref to a player-struct that isn't on any team. (defn make-player [name] (ref (struct player-struct name))) ; Makes a new Ref to a team-struct that contains no players. (defn make-team [name] (ref (struct team-struct name []))) (defn assign-player-to-team [player-ref new-team-ref] (dosync ; If the player has a former team, remove them from it. (if-let [old-team-ref (@player-ref :team-ref)] (let [old-player-refs (@old-team-ref :player-refs) new-player-refs (remove #(= % player-ref) old-player-refs)] (alter old-team-ref assoc :player-refs new-player-refs))) ; Add the player to their new team. (let [old-player-refs (@new-team-ref :player-refs) new-player-refs (conj old-player-refs player-ref)] (alter player-ref assoc :team-ref new-team-ref) (alter new-team-ref assoc :player-refs new-player-refs ; Returns a string describing a given player. (defn player-to-string [player-ref] (dosync (str (@player-ref :name) " plays for " (if-let [team-ref (@player-ref :team-ref)] (str "the " (@team-ref :name)) "nobody") "."))) ; Returns a string describing a given team. (defn team-to-string [team-ref] (dosync (apply str (@team-ref :name) " roster:" (map (fn [player-ref] (str "\n " (@player-ref :name))) (@team-ref :player-refs) ; players1 and players2 are collections of Refs to player StructMaps. ; Neither can be empty. ; All players in a collection must be on the same team. (defn trade [players1 players2] (dosync (let [team1 ((first players1) :team-ref) team2 ((first players2) :team-ref)] (doseq [p players1] (assign-player-to-team p team2)) (doseq [p players2] (assign-player-to-team p team1) (let [oilers (make-team "Oilers") kings (make-team "Kings") p1 (make-player "Wayne Gretzky") p2 (make-player "Mike Krushelnyski") p3 (make-player "Marty McSorley") p4 (make-player "Jimmy Carson") p5 (make-player "Martin Gelinas")] (doseq [p [p1 p2 p3]] (assign-player-to-team p oilers)) (doseq [p [p4 p5]] (assign-player-to-team p kings)) (println "Before trade:") (println (team-to-string oilers)) (println (team-to-string kings)) (trade [p1 p2 p3] [p4 p5]) (println "\nAfter trade:") (println (team-to-string oilers)) (println (team-to-string kings))) -- 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 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: ANN: FnParse, a functional parsing library
Thanks for the tip on looking at clojure.contrib. I keep forgetting to check there. On Jul 5, 2009, at 4:20 PM, samppi wrote: > > If you need a JSON parser, there's already a good one included with > clojure.contrib. The one with the FnParse library is just a sample to > show how it works. But please feel free to use it however it can be > useful to you. :) > > On Jul 4, 1:45 pm, Wilson MacGyver wrote: >> Very timely, I need to parse a bunch on JSON files on Monday :) good >> work >> >> Sent from my iPhone >> >> On Jul 4, 2009, at 3:16 PM, samppi wrote: >> >> >> >> >> >>> I'm pleased to announce FnParse, a monadic functional parsing >>> library >>> for Clojure, half a year in the making. I started on FnParse in >>> December as my first Clojure project, and now it has matured to >>> something that I believe is very and immediately useful. Currently, >>> I'm writing a YAML parser using FnParse. >> >>> With FnParse, you can easily parse a string or any sequence of >>> tokens >>> into native data structures. FnParse is based on the concept of the >>> rule, a self-contained function that accepts a state data structure, >>> containing a sequence of tokens, and either consumes some tokens-- >>> turning them into new data--or fails. Rules correspond nicely to >>> EBNF >>> productions and productions in other sort of grammars. FnParse >>> provides common rules, functions that create new rules, and >>> functions >>> that facilitate using rules. >> >>> A sample JSON parser is athttp://wiki.github.com/joshua-choi/ >>> fnparse/sample-json-parser >>> . >>> Online documentation is available at:http://wiki.github.com/joshua- >>> choi/fnparse >>> . >>> The source is at:http://github.com/joshua-choi/fnparse. >> >>> If you are confused about anything or find any bugs, please create >>> an >>> issue on GitHub (http://github.com/joshua-choi/fnparse/issues) or >>> send >>> me a message on GitHub. > > --~--~-~--~~~---~--~~ 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: sanity check needed
A set might be better to hold the player-refs, then you can just call (disj player-refs player-ref) without doing any extra checking. Also you can access ref values without needing to be in a dosync. Things being immutable, the value you get from, say, @team-ref won't change once you have it. On Jul 5, 5:12 pm, Mark Volkmann wrote: > I wrote some fairly simple code to demonstrate use of StructMaps and > Refs. It's 80 lines including comments. I'd appreciate it if someone > could look it over and let me know if I've done anything that isn't > very idiomatic. > > The program models sports teams and players. The main functionality is > the ability to trade sets of players between teams. Both teams and > players are held by Refs. Players have a reference to their team. > Teams have references to their players. > > The output from the code follows: > > Before trade: > Oilers roster: > Wayne Gretzky > Mike Krushelnyski > Marty McSorley > Kings roster: > Jimmy Carson > Martin Gelinas > > After trade: > Oilers roster: > Martin Gelinas > Jimmy Carson > Kings roster: > Wayne Gretzky > Mike Krushelnyski > Marty McSorley > > Here's the code: > > ; A player knows his team, if any. > (defstruct player-struct :name :team-ref) > > ; A team knows its players. > (defstruct team-struct :name :player-refs) > > ; Makes a new Ref to a player-struct that isn't on any team. > (defn make-player [name] > (ref (struct player-struct name))) > > ; Makes a new Ref to a team-struct that contains no players. > (defn make-team [name] > (ref (struct team-struct name []))) > > (defn assign-player-to-team [player-ref new-team-ref] > (dosync > ; If the player has a former team, remove them from it. > (if-let [old-team-ref (@player-ref :team-ref)] > (let [old-player-refs (@old-team-ref :player-refs) > new-player-refs (remove #(= % player-ref) old-player-refs)] > (alter old-team-ref assoc :player-refs new-player-refs))) > > ; Add the player to their new team. > (let [old-player-refs (@new-team-ref :player-refs) > new-player-refs (conj old-player-refs player-ref)] > (alter player-ref assoc :team-ref new-team-ref) > (alter new-team-ref assoc :player-refs new-player-refs > > ; Returns a string describing a given player. > (defn player-to-string [player-ref] > (dosync > (str (@player-ref :name) " plays for " > (if-let [team-ref (@player-ref :team-ref)] > (str "the " (@team-ref :name)) > "nobody") > "."))) > > ; Returns a string describing a given team. > (defn team-to-string [team-ref] > (dosync > (apply str > (@team-ref :name) " roster:" > (map > (fn [player-ref] (str "\n " (@player-ref :name))) > (@team-ref :player-refs) > > ; players1 and players2 are collections of Refs to player StructMaps. > ; Neither can be empty. > ; All players in a collection must be on the same team. > (defn trade [players1 players2] > (dosync > (let [team1 ((first players1) :team-ref) > team2 ((first players2) :team-ref)] > (doseq [p players1] > (assign-player-to-team p team2)) > (doseq [p players2] > (assign-player-to-team p team1) > > (let [oilers (make-team "Oilers") > kings (make-team "Kings") > p1 (make-player "Wayne Gretzky") > p2 (make-player "Mike Krushelnyski") > p3 (make-player "Marty McSorley") > p4 (make-player "Jimmy Carson") > p5 (make-player "Martin Gelinas")] > > (doseq [p [p1 p2 p3]] > (assign-player-to-team p oilers)) > (doseq [p [p4 p5]] > (assign-player-to-team p kings)) > > (println "Before trade:") > (println (team-to-string oilers)) > (println (team-to-string kings)) > > (trade [p1 p2 p3] [p4 p5]) > > (println "\nAfter trade:") > (println (team-to-string oilers)) > (println (team-to-string kings))) > > -- > 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 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: sanity check needed
On Jul 5, 2009, at 8:12 PM, Mark Volkmann wrote: I'd appreciate it if someone could look it over and let me know if I've done anything that isn't very idiomatic. A few recommendations just at the "look and feel" level: - use doc strings for functions in place of comments - global delete of "-ref". Those suffixes make the code look noisy without adding enough value to warrant that. - refs don't need to be dereferenced explicitly when in calling position. Whenever possible, elide @: (@foo ...) -> (foo ...), again for visual noise reduction. --Steve smime.p7s Description: S/MIME cryptographic signature
Re: sanity check needed
I should have been more clear when I said to use (disj ...); I meant sending that via an alter. On Jul 5, 6:05 pm, ataggart wrote: > A set might be better to hold the player-refs, then you can just call > (disj player-refs player-ref) without doing any extra checking. > > Also you can access ref values without needing to be in a dosync. > Things being immutable, the value you get from, say, @team-ref won't > change once you have it. > > On Jul 5, 5:12 pm, Mark Volkmann wrote: > > > > > I wrote some fairly simple code to demonstrate use of StructMaps and > > Refs. It's 80 lines including comments. I'd appreciate it if someone > > could look it over and let me know if I've done anything that isn't > > very idiomatic. > > > The program models sports teams and players. The main functionality is > > the ability to trade sets of players between teams. Both teams and > > players are held by Refs. Players have a reference to their team. > > Teams have references to their players. > > > The output from the code follows: > > > Before trade: > > Oilers roster: > > Wayne Gretzky > > Mike Krushelnyski > > Marty McSorley > > Kings roster: > > Jimmy Carson > > Martin Gelinas > > > After trade: > > Oilers roster: > > Martin Gelinas > > Jimmy Carson > > Kings roster: > > Wayne Gretzky > > Mike Krushelnyski > > Marty McSorley > > > Here's the code: > > > ; A player knows his team, if any. > > (defstruct player-struct :name :team-ref) > > > ; A team knows its players. > > (defstruct team-struct :name :player-refs) > > > ; Makes a new Ref to a player-struct that isn't on any team. > > (defn make-player [name] > > (ref (struct player-struct name))) > > > ; Makes a new Ref to a team-struct that contains no players. > > (defn make-team [name] > > (ref (struct team-struct name []))) > > > (defn assign-player-to-team [player-ref new-team-ref] > > (dosync > > ; If the player has a former team, remove them from it. > > (if-let [old-team-ref (@player-ref :team-ref)] > > (let [old-player-refs (@old-team-ref :player-refs) > > new-player-refs (remove #(= % player-ref) old-player-refs)] > > (alter old-team-ref assoc :player-refs new-player-refs))) > > > ; Add the player to their new team. > > (let [old-player-refs (@new-team-ref :player-refs) > > new-player-refs (conj old-player-refs player-ref)] > > (alter player-ref assoc :team-ref new-team-ref) > > (alter new-team-ref assoc :player-refs new-player-refs > > > ; Returns a string describing a given player. > > (defn player-to-string [player-ref] > > (dosync > > (str (@player-ref :name) " plays for " > > (if-let [team-ref (@player-ref :team-ref)] > > (str "the " (@team-ref :name)) > > "nobody") > > "."))) > > > ; Returns a string describing a given team. > > (defn team-to-string [team-ref] > > (dosync > > (apply str > > (@team-ref :name) " roster:" > > (map > > (fn [player-ref] (str "\n " (@player-ref :name))) > > (@team-ref :player-refs) > > > ; players1 and players2 are collections of Refs to player StructMaps. > > ; Neither can be empty. > > ; All players in a collection must be on the same team. > > (defn trade [players1 players2] > > (dosync > > (let [team1 ((first players1) :team-ref) > > team2 ((first players2) :team-ref)] > > (doseq [p players1] > > (assign-player-to-team p team2)) > > (doseq [p players2] > > (assign-player-to-team p team1) > > > (let [oilers (make-team "Oilers") > > kings (make-team "Kings") > > p1 (make-player "Wayne Gretzky") > > p2 (make-player "Mike Krushelnyski") > > p3 (make-player "Marty McSorley") > > p4 (make-player "Jimmy Carson") > > p5 (make-player "Martin Gelinas")] > > > (doseq [p [p1 p2 p3]] > > (assign-player-to-team p oilers)) > > (doseq [p [p4 p5]] > > (assign-player-to-team p kings)) > > > (println "Before trade:") > > (println (team-to-string oilers)) > > (println (team-to-string kings)) > > > (trade [p1 p2 p3] [p4 p5]) > > > (println "\nAfter trade:") > > (println (team-to-string oilers)) > > (println (team-to-string kings))) > > > -- > > 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 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: sanity check needed
On Sun, Jul 5, 2009 at 8:05 PM, ataggart wrote: > > A set might be better to hold the player-refs, then you can just call > (disj player-refs player-ref) without doing any extra checking. Thanks, I llke that much better! > Also you can access ref values without needing to be in a dosync. > Things being immutable, the value you get from, say, @team-ref won't > change once you have it. Yeah, but in my case I am accessing more than one ref value inside each dosync and I want to make sure I get consistent values. For example, if a trade is being executed in one thread and one of the teams involved is being printed in another thread, I could get inconsistent output without the dosyncs. Thanks for the feedback! -- 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 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: sanity check needed
On Sun, Jul 5, 2009 at 8:14 PM, Stephen C. Gilardi wrote: > > On Jul 5, 2009, at 8:12 PM, Mark Volkmann wrote: > > I'd appreciate it if someone > could look it over and let me know if I've done anything that isn't > very idiomatic. > > A few recommendations just at the "look and feel" level: > - use doc strings for functions in place of comments Thanks! I temporarily forget about those. > - global delete of "-ref". Those suffixes make the code look noisy without > adding enough value to warrant that. I agree it makes the code look noisy, but I like that it helps me remember that a value is a ref. I'll remove them though because I know I'm in the minority on that viewpoint. > - refs don't need to be dereferenced explicitly when in calling position. > Whenever possible, elide @: (@foo ...) -> (foo ...), again for visual noise > reduction. Wow! I don't know how I missed out on that rule. I don't recall every hearing about that feature. Very cool! Is this discussed in the "Programming Clojure" book? -- 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 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: print-base / print-radix?
On Jul 5, 9:02 pm, Tom Faulhaber wrote: > Parth, > > I've created a little wrapper as promised at:http://gist.github.com/141001. > > It gives you my-pprint: > > user> (binding [*print-base* 2] (my-pprint (range 10))) > (0 1 10 11 100 101 110 111 1000 1001) > nil > user> > Thanks Tom. This works beautifully :) Here is the example that earlier example in the thread: user=> (binding [wrap-base/*print-base* 16] (wrap-base/my-pprint (decode :b32 (test-ops 3 {:inst {:prefix (), :code (c7 45 f8 a 0 0 0), :op :movl, :args [{:type :Ev-mem, :arg {:reg :ebp, :disp -8}} a]}, :more ()} nil user=> > While doing this, I realized to my horror that ~r doesn't do 0 > correctly for non-standard bases. I'll fix that soon. > > Also, I've started to implement *print-radix* and *print-base* for > real in cl-format and the pretty printer, so those should be available > soon. > Fantastic ... pprint just keeps getting better :) Regards, Parth > Enjoy, > > Tom > > On Jul 3, 3:16 am, Parth wrote: > > > On Jul 3, 11:25 am, Tom Faulhaber wrote: > > > > Parth, > > > > I was thinking about this a little more today and I came up with a way > > > to extend the pretty printer easily to support *print-radix* with a > > > little wrapper. I'll try to get a chance to write it up for you > > > tomorrow. > > > > Tom > > > Sounds perfect. Thanks very much :) > > > Regards, > > Parth > > > > On Jul 2, 6:29 pm, Parth wrote: > > > > > On Jul 3, 6:15 am, Parth wrote: > > > > > > Tom, Chouser, Thanks for your responses. > > > > > > As of now I am doing the same thing as suggested. > > > > > However, this tends be become painful the moment structures > > > > > start to nest. For e.g. I am using Clojure to decode a bit > > > > > of assembly and below is what I end up doing to see the > > > > > values of interest in hex: > > > > > > user=> (decode :b32 (nth test-ops 3)) > > > > > {:inst {:prefix (), :code (199 69 248 10 0 0 0), :op :movl, :args > > > > > [{:type :Ev-mem, :arg {:reg :ebp, :disp -8}} 10]}, :more ()} > > > > > user=> (def r (decode :b32 (nth test-ops 3))) > > > > > #'user/r > > > > > user=> (map hex (get-in r [:inst :code])) > > > > > ("c7" "45" "f8" "a" "0" "0" "0") > > > > > user=> (hex (second (get-in r [:inst :args]))) > > > > > "a" > > > > > user=> > > > > > > Basically, I need to extract each number seq or value > > > > > individually and print it in hex for every instruction I > > > > > decode and view. > > > > > > This isn't too much fun to do in the middle of a debug session :) > > > > > > Having something like *print-base* would be ideal IMHO > > > > > would make scenarios like this really easy as one could > > > > > simply do: > > > > > > user=> (set! *print-base* 16) > > > > > user=> (decode :b32 (nth test-ops 3)) > > > > > {:inst {:prefix (), :code (c7 47 f8 a 0 0 0), :op :movl, :args > > > > > [{:type :Ev-mem, :arg {:reg :ebp, :disp f8}} a]}, :more ()} > > > > > > In the absence of this I thought of writing a function > > > > > that would take an arbitrary Clojure structure/coll and print > > > > > it out in the manner like above. But then it won't > > > > > be much different from pprint with radix support but without > > > > > the pretty part. > > > > > > I suppose what I am hoping is that a feature request for > > > > > *print-base* sort of a mechanism get considered > > > > > for Clojure as it makes scenarios like the above very > > > > > easy to deal with. Any chance of this being somewhere > > > > > on the Clojue todo? :) > > > > > Rich, > > > > > If this is something you think would be a good addition > > > > to Clojure I could give a shot at creating a patch for > > > > this (with a CA of course). Please let me know. > > > > > I think rather than a generic radix support, if > > > > we have hex, bin and octal supported, most uses > > > > cases should be covered. > > > > > Regards, > > > > Parth > > > > > > I will probably create a poor mans radix based print > > > > > in the mean time for the this scenario. That should > > > > > be an interesting exercise. > > > > > > Thanks, > > > > > Parth > > > > > > On Jul 2, 10:58 pm, Chouser wrote: > > > > > > > On Thu, Jul 2, 2009 at 4:51 AM, Parth > > > > > > > Malwankar wrote: > > > > > > > > I frequently deal with hex and binary numbers. > > > > > > > As of now when I need to view a list of numbers > > > > > > > I just map a little hex function to it to translate it > > > > > > > into a list of hex strings at the repl. > > > > > > > > Having something like *print-base* / *print-radix* [1] may be > > > > > > > valuable in such a scenario > > > > > > > I don't think Java's built-in formatter is nearly as > > > > > > flexible as those, but getting hex or octal strings is easy > > > > > > enough: > > > > > > > user=> (format "%d" 255) > > > > > > "255" > > > > > > user=> (format "%o" 255) > > > > > > "377" > > > > > > user=> (format "%x" 255) > > > > > > "ff" > > > > > > user=> (format "%X" 255) > > > > > > "FF" > > > > > > > --Chouser --~--~-
Re: Clojure at LispNYC tonight 7pm
I second this suggestion to add the video to clojure.blip.tv. It felt very awkward in 2009 to have to download this thing instead of stream it. :) I just watched it and wanted to say it's a very nice show of Clojure's Java interop in practice. Congrats to Stuart. It was also very nice to learn the history behind some of Stuart's contribs. Now, I think it would be very great for Stuart to present this again, but this time to a java audience, and put that too on blip. On Jun 16, 11:10 am, Paul Stadig wrote: > On Wed, Jun 10, 2009 at 11:37 AM, Stuart Sierra > > wrote: > > > On Jun 9, 10:32 am, Stuart Sierra wrote: > > > Join us Tuesday, June 9 from 7:00-9:00 for Stuart Sierra's > > > presentation: > > > > Implementing AltLaw.org in Clojure > > > Slides and video here:http://lispnyc.org/wiki.clp?page=past-meetings > > We'll try to get something lighter than a 3GB mpeg soon. > > > -Stuart > > I watched this video. Thanks for posting it! There is some great information > in there, especially the "from the trenches" tips about working with Java > libraries. > > Since you're one of the more active contributors to Clojure, would it be > appropriate to post the video to clojure.blip.tv? > > Paul --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
tests involving threads
Very glad that test is now part of clojure core. I've run into 2 strange behaviours when trying to write tests where threads are involved. My case is a little complex so here is a minimal version which shows what I mean: test-test.clj: (ns test-test (:use clojure.test)) (deftest testathon (let [f1 (future (is (= 1 2))) f2 (future (future (/ 1 0)))] @f1 @f2)) (run-tests) (shutdown-agents) $ clj test-test.clj Testing test-test FAIL in clojure.lang.persistentlist$emptyl...@1 (test-test.clj:5) expected: (= 1 2) actual: (not (= 1 2)) Ran 1 tests containing 0 assertions. 0 failures, 0 errors. f1 failed, and a FAIL message is printed, but the end report indicates 0 failures. f2 raised an exception silently. I guess I'm just not "doing it right"! 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 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: loneclojurian at ICFP programming contest
On Jul 5, 3:18 am, fft1976 wrote: > On Jul 5, 2:31 am, Nicolas Oury wrote: > > > After, when I run the benchmark in -server with a big enough CacheCode area > > (1000m), and enough iterations to have everything JITed, I get more than > > 860.000 iterations per second. (I benchmarked 100 000 000 iterations in 121 > > sec, on my 2.4GHz computer). > > That's 3000 clock cycles per VM instruction? I'm not very familiar > with the problem, but I thought "straight" C bytecode interpreters > were at around 30 and compiling the VM code to native code (with JIT) > reduced it to 7. Is this right? On modern architectures, measuring performance in clock cycles is almost meaningless. I spend a reasonably amount of my working life making code run faster on game consoles; what I say here applies even more to modern x86 chips. After you have the best algorithm for the job, you very quickly find that going fast is entirely bound by memory speed (actually latency) - cache misses are the enemy. Obviously, in higher level languages like Clojure you need to take a few extra steps - get the right algorithm & make sure you are writing your code in a way that the JIT can optimize well. Once that is done you would ideally run a profiler that points out where you have cache misses - I think vTune does this. You can fake pre-fetching by issuing a read one cacheline ahead in your mainloop, though the JVM may drop this as useless work. If the JVM supported proper cache line fetching & zeroing, that would make high performance Java programs easier to write. BTW, I noticed that you mention that Clojure is not living up to its performance hype. In my experience, the biggest performance impact on code is who wrote it. It makes me cry when I see linear linked-list search of 5000+ strings using strcmp. Brad --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---