Return value of load
Hi, load-reader and load-string currently return the last value from the code loaded. This is actually nice. As waterfront I'd like to use this to load plugins, which then simply return a structure with information about the plugin as last value. I'd like to distribute some standard plugins in the application's jar file. However load unfortunately returns nil. So loading via load doesn't work. Is there some specific reason for that or could load be adapted to also return the last value evaluated? Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: loneclojurian at ICFP programming contest
On Jul 3, 5:52 pm, Jon Harrop wrote: > On Thursday 02 July 2009 07:58:11 you wrote: > > > I wonder if Jon Harrop is still planning to write Clojure for > > Scientists or Scala for Scientists or both? > > I am certainly interested in writing both books. I reviewed Scala back in 2007 > and decided that it was not ready to be advocated. Perhaps things have > progressed significantly since then but my impression is that Clojure is > developing in a more productive direction and much more rapidly. I am also > more interested in Clojure because it strives to be a genuine functional > language rather than an OOP language with some odds and sods bolted on (Scala > feels like a minor departure from Java to me, and I am not a Java fan. In > fact, more like C# 3 than any real functional language) and because Clojure > is designed with industrial use in mind rather than as an academic exercise. > However, I have yet to give Clojure the thorough study that it deserves > simply because I am tied up getting our F# products ready for its big release > in 2010. > > If anyone here is interested in a Clojure book aimed at technical users > (scientists and engineers), please let me know. I'd probably be interested if Clojure lived up to the promise of being as fast as anything on JVM, and JVM lived up to the promise of being as fast as C++, but I'm afraid that's not happening, as this thread indicates. --~--~-~--~~~---~--~~ 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
Hello, after experimenting a bit, it seems that you can get a small gain by putting things in local variables (25% or so) but not much. I looked at the implementation and I was assuming something that is not true: aset-double does not compile to JVM instructions for setting the array directly. It calls a method setDouble. I think the big difference between Clojure and java comes from that. When you write r[i] = ... in java, I believe it is compiled to not much more than a few bytecode instructions to arrange the stack and one to store in an array. When we do the same in Clojure, we call a function that call a method, that does that. As setting an array is very quick, even the slight overhead of calling a method makes the program far slower, in a tight loop. I will start another thread to ask whether this is really the problem and if it can be solved. 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 -~--~~~~--~~--~--~---
aset-* family of functions
Dear all, In another thread, we realized that setting an array of primitive type (it was double in our example) is far quicker in Java than in Clojure. After looking to the implementation of aset-* in Clojure 1.0, I realize that it calls the set* method of java.reflect.Array. Is there a way of avoiding that? Could the aset-* and aget family was not special forms implemented using their JVM bytecode counterparts. (dastore, in this example) Is it something impossible to do? Or not a good idea? Or to be done later? There have been some long threads about scientific programs in Clojure, and having array access to primitive types as fast as in java would be a good start to authorize cpu intensive programs to be written in clojure. Best regards, 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 -~--~~~~--~~--~--~---
nth yields "java.lang.OutOfMemoryError: Java heap space"
Using a fairly recent 1.1 snapshot, I get an OutOfMemoryError for this: (defn fib-seq [] ((fn more [a b] (lazy-seq (cons a (more b (+ a b) 0 1) ) (nth (fib-seq) 20) However, this works fine: (defn xth [coll i] (if (zero? i) (first coll) (recur (rest coll) (dec i (xth (fib-seq) 20) Am I doing anything wrong, or is this a bug? --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
Jazz - a wrapper DSL for JGoodies Forms
Dear Clojurians, I worked a little on the feedback of Laurent and Nicolas. This led to several changes: * clj-forms is now called "Jazz" * Jazz now provides so-called editors for different types, currently: String, Boolean, Integer, :Enum more to come... I'm still not totally rid of the col-spec and constraint parameters, but this will hopefully change soon.. New URLs: * http://kotka.de/projects/clojure/jazz.html * http://bitbucket.org/kotarak/jazz * http://bitbucket.org/kotarak/jazz/wiki/Home Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: Return value of load
On Jul 4, 2009, at 4:02 AM, Meikel Brandmeyer wrote: Is there some specific reason for that or could load be adapted to also return the last value evaluated? I experimented with this, got it to work for a simple case, and prepared my initial reply below. In working with the idea some more though, I think there is a show-stopper problem with it. In the case of an AOT compiled Clojure file, it's loaded (ultimately) with Class.forName. I don't see a way to retrieve the last eval'd expression from such a load. I now think the idea of returning a usable value from load is not reliable/general enough to be worth doing. For the case you described, I recommend the method I described below: require the plugin file to define a function with a well-known name in its namespace and call that function after loading the plugin. --Steve my initial reply: load could be adapted. I experimented and I have it working on my machine. The several variants of loadResourceScript and load in RT.java need to be changed to return Object. Also, clojure.core/load currently supports loading multiple libs with one call, but apparently that's never used in clojure.core or clojure.contrib. Changing its signature to accept only one lib name would facilitate returning a value. I did that in my experiment and all tests still pass. I see returning a value from load as a nice functional thing to do. On the other hand, I view loading as primarily state-changing: adding to the capabilities of the running Clojure by loading in libs that implement namespaces. To the greatest extent possible, I think Clojure source files should contain only definitions--a view that embraces a clear distinction between load/compile time and run time. In the case you describe, I think it would be clearer to require that your plugin files define a function with a specified name (like "plugin-info") that can be called after they are loaded to return the info you require. This would be similar to having Java plugins implement a "de.kotka.Plugin" interface (for example). This would make your intention for these files explicit both within their body and in your plugin loading code. All that being said, I think changing the "load" suite of functions in clojure.core and clojure.lang.RT to return the last thing evaluated would make Clojure strictly more powerful and I'll be happy to provide a patch if an issue requesting it is welcome. --Steve smime.p7s Description: S/MIME cryptographic signature
Re: nth yields "java.lang.OutOfMemoryError: Java heap space"
On Jul 4, 2009, at 6:04 AM, arasoft wrote: > > Using a fairly recent 1.1 snapshot, I get an OutOfMemoryError for > this: > > (defn fib-seq [] >((fn more [a b] >(lazy-seq (cons a (more b (+ a b) > 0 1) > ) > > (nth (fib-seq) 20) > > However, this works fine: > > (defn xth [coll i] > (if (zero? i) (first coll) (recur (rest coll) (dec i > > (xth (fib-seq) 20) > > Am I doing anything wrong, or is this a bug? You aren't doing anything wrong, it's just that recur is a local jump which creates no stack and calling a function recursively is not. In other words Clojure doesn't have built-in tail call elimination, but recur creates the same effect. (I actually prefer this behavior because it's easy to see where you're paying the penalty for recursion and where you aren't, unlike in OCaml, Scheme and Haskell, where it can be easy to get confused about which form is the final position.) — Daniel Lyons --~--~-~--~~~---~--~~ 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: nth yields "java.lang.OutOfMemoryError: Java heap space"
On Jul 4, 4:37 pm, Daniel Lyons wrote: > On Jul 4, 2009, at 6:04 AM, arasoft wrote: > > Using a fairly recent 1.1 snapshot, I get an OutOfMemoryError for > > this: > > > (defn fib-seq [] > > ((fn more [a b] > > (lazy-seq (cons a (more b (+ a b) > > 0 1) > > ) > > > (nth (fib-seq) 20) > > > However, this works fine: > > > (defn xth [coll i] > > (if (zero? i) (first coll) (recur (rest coll) (dec i > > > (xth (fib-seq) 20) > > > Am I doing anything wrong, or is this a bug? > > You aren't doing anything wrong, it's just that recur is a local jump > which creates no stack and calling a function recursively is not. In > other words Clojure doesn't have built-in tail call elimination, but > recur creates the same effect. (I actually prefer this behavior > because it's easy to see where you're paying the penalty for recursion > and where you aren't, unlike in OCaml, Scheme and Haskell, where it > can be easy to get confused about which form is the final position.) I don't think this explains it. It is a OutOfMemoryError not a stack overflow. It is not a recursion problem. I think it is that nth hangs on to the head of the lazy fib sequence, and therefor all the elements including the big integers can not be garbage collected. The xth function does not hang on to the head, and all the intermediate elements can be garbage collected. //Lennart Staflin --~--~-~--~~~---~--~~ 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 Sat, Jul 4, 2009 at 4:50 AM, Nicolas Oury wrote: > Hello, > > after experimenting a bit, it seems that you can get a small gain by putting > things in local variables (25% or so) but not much. > > I looked at the implementation and I was assuming something that is not > true: > aset-double does not compile to JVM instructions for setting the array > directly. > It calls a method setDouble. I think the big difference between Clojure and > java comes from that. > When you write r[i] = ... in java, I believe it is compiled to not much more > than a few bytecode instructions to arrange the stack and > one to store in an array. > > When we do the same in Clojure, we call a function that call a method, that > does that. As setting an array is very quick, even the slight overhead of > calling a method makes the program far slower, in a tight loop. > > I will start another thread to ask whether this is really the problem and if > it can be solved. > With -server, HotSpot inlines the calls to static methods generated by aset on arrays of primitives to the exact same machine instructions. People that want to match the performance of Java on arrays of primitives need to follow the advice given here carefully: http://clojure.org/java_interop#primitives http://clojure.org/java_interop#optimization In particular, aget/aset are overloaded for arrays of primitives. aset-xxx are not. 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: aset-* family of functions
On Sat, Jul 4, 2009 at 5:00 AM, Nicolas Oury wrote: > Dear all, > > In another thread, we realized that setting an array of primitive type (it > was double in our example) is far quicker in > Java than in Clojure. > > After looking to the implementation of aset-* in Clojure 1.0, I realize that > it calls the set* method of java.reflect.Array. > Is there a way of avoiding that? > > Could the aset-* and aget family was not special forms implemented using > their JVM bytecode counterparts. (dastore, in this example) > Is it something impossible to do? Or not a good idea? Or to be done later? > > There have been some long threads about scientific programs in Clojure, and > having array access to primitive types as fast as in java would be a good > start to authorize cpu intensive programs to be written in clojure. > > As I replied in the other thread, the ways to get primitive array access as fast as Java are documented here: http://clojure.org/java_interop#primitives http://clojure.org/java_interop#optimization 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: aset-* family of functions
Thanks for the reply. It seems to speed up quite a bit the array of double. I cannot manage to make it work for the array of booleans. Is there someting different? If aset and aget are faster, what is the goal of the aset-xxx? 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: parsing program for nested parens and square brackets
(def matches {\( \) \[ \]}) (defn balanced? [s] (empty? (reduce #(if (= (matches (peek %1)) %2) (pop %1) (conj %1 %2)) [] s))) Learning Clojure. So far I'm really liking it. This is the first time I've tried anything outside of some REPL incantations from books, blogs, this list, etc thus it wouldn't be a total surprise if it's not idiomatic or correct in some way. It does seem to work although it could be more efficient if it could bail earlier on some of the false strings On Fri, Jul 3, 2009 at 9:13 PM, carlitos wrote: > > > Probably the following is much less efficient than the other solutions > proposed, but I find it easier to understand (and if I didn't > misunderstand the problem it gives the right answer). > > (defn simplify-1 > "remove adjacent pairs of opening/closing brackets" > ([string] (simplify-1 "" string)) > ([prefix [a & [b & cdef :as bcdef]]] > (cond (nil? a) prefix > (#{"()" "[]"} (str a b)) (recur prefix cdef) > :otherwise (recur (str prefix a) bcdef > > (defn simplify [s] > (let [ss (simplify-1 s)] >(if (= ss s) ss (recur ss > > (defn balanced? [s] > (empty? (simplify s))) > > Cheers, > > Carlos > > > --~--~-~--~~~---~--~~ 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: nth yields "java.lang.OutOfMemoryError: Java heap space"
Hi, Am 04.07.2009 um 17:11 schrieb Lennart Staflin: I don't think this explains it. It is a OutOfMemoryError not a stack overflow. It is not a recursion problem. I think it is that nth hangs on to the head of the lazy fib sequence, and therefor all the elements including the big integers can not be garbage collected. The xth function does not hang on to the head, and all the intermediate elements can be garbage collected. This was my first thought, too. But this is not the case. If the collection "is" Sequential, the seq is obtained from it via seq() and then the original pointer is nulled. Maybe this gets optimised away by the JVM? Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: nth yields "java.lang.OutOfMemoryError: Java heap space"
On Jul 4, 8:04 am, arasoft wrote: > Using a fairly recent 1.1 snapshot, I get an OutOfMemoryError for > this: > > (defn fib-seq [] > ((fn more [a b] > (lazy-seq (cons a (more b (+ a b) > 0 1) > ) > > (nth (fib-seq) 20) > > However, this works fine: > > (defn xth [coll i] > (if (zero? i) (first coll) (recur (rest coll) (dec i > > (xth (fib-seq) 20) > > Am I doing anything wrong, or is this a bug? A recent optimization attempt introduced a head-retaining hop in RT.nth, now removed. Thanks for the report! http://github.com/richhickey/clojure/commits/master 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 -~--~~~~--~~--~--~---
Type annotations in libraries
I thought I'd share an observation with the group. I'm walking through my fork of Dan Larkin and Phil Hagelberg's HTTP client library, fixing reflection warnings and generally seeing if I can add some features (to bring it up to parity with some code I've written that uses the Apache HTTP libraries -- proxy settings being one example). One such warning comes from a use of as-str, in clojure.contrib.java- utils. This function is (defn as-str "Returns the name or string representation of x" [x] (if (instance? clojure.lang.Named x) (name x) (str x))) Obviously (to a human) this always returns a string, but as-str's return type is not labeled as such, and so (set! *warn-on-reflection* true) (use 'clojure.contrib.java-utils) (defn foo [x] (.toLowerCase (as-str x))) will produce a warning that toLowerCase can't be resolved. Presumably the generated code will incur a cost for reflection, turning a trivial utility function into an unexpectedly expensive operation. It strikes me that it's somewhat ugly to force users of libraries to settle for reflection, write code like (defn foo [x] (let [#^String s (as-str x)] (.toLowerCase s))) or (defn foo [x] (.toLowerCase #^String (as-str x))) or -- worse -- end up rewriting library code to avoid the need for such annotations. I expect that static analysis could avoid the need for explicit annotations in many cases, but Sufficiently Smart Compilers take time, and I don't expect one any time soon. Perhaps we should all try to ensure that -- wherever practical -- straightforward uses of our libraries' public interfaces don't incur reflection warnings? Please don't interpret this as a complaint: I simply feel that publishing libraries (particularly in contrib) entails a duty to do things "clean and right", and maybe folks hadn't thought about this issue yet. Thoughts? I would have no trouble simply issuing pull requests to add type annotations to contrib libraries, but I would feel a bit silly opening issues and generating manual patch files for the odd #^String. -R --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
ANN: FnParse, a functional parsing library
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 at http://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: Return value of load
Hi Stephen, thanks for your thoughts. Am 04.07.2009 um 16:19 schrieb Stephen C. Gilardi: Is there some specific reason for that or could load be adapted to also return the last value evaluated? I experimented with this, got it to work for a simple case, and prepared my initial reply below. In working with the idea some more though, I think there is a show-stopper problem with it. In the case of an AOT compiled Clojure file, it's loaded (ultimately) with Class.forName. I don't see a way to retrieve the last eval'd expression from such a load. Ok. That would of course be too much buck for the bang. For the case you described, I recommend the method I described below: require the plugin file to define a function with a well- known name in its namespace and call that function after loading the plugin. That was the other way, I considered. I think, requiring plugins to be on the classpath is not really an option, this it would make the application too static. But having a similar convention for the plugin nameing as for namespaces, that would probably be sufficient for load-reader. I think, I will change my implementation to work like that. Also, clojure.core/load currently supports loading multiple libs with one call, but apparently that's never used in clojure.core or clojure.contrib. Changing its signature to accept only one lib name would facilitate returning a value. I did that in my experiment and all tests still pass. Aargh. Hadn't thought of that. You are right. In fact I load several files with one load, in several of my projects. In the case you describe, I think it would be clearer to require that your plugin files define a function with a specified name (like "plugin-info") that can be called after they are loaded to return the info you require. This would be similar to having Java plugins implement a "de.kotka.Plugin" interface (for example). This would make your intention for these files explicit both within their body and in your plugin loading code. Yes. This is the right way to go. However I was a bit concerned about the nameing. I don't want to have to specify the file *and* the namespace. But with a plugin nameing convention (read "the usual namespace nameing convention") this is not really a problem, I guess. Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: ANN: FnParse, a functional parsing library
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 at > http://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 -~--~~~~--~~--~--~---
particle demo
hi, 1) little particle demo, attached. me trying to learn Clojure by ripping off Rich's ants code. 2) in the repl you can do hot-code-swap (in the vein of Erlang, JavaRebel, etc.) care of agents; see the bottom of the file for examples. 3) i have not run it under a profiler yet. 4) please suggest optimizations / style improvements. sincerely. --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~--- pdem.clj Description: Binary data
adding a member to a set in a map in a map in a map in a ref
Say I have a data structure like this (def ref-map-map-map-set (ref {:key1 {:key2 {:key3 #{)) If I want to add a new member to the set which is the value of :key3, I currently do this: (dosync (let [key1 (:key1 @ref-map-map-map-set) key2 (:key2 key1) key3 (:key3 key2)] (ref-set ref-map-map-map-set (assoc @ref-map-map-map-set :key1 (assoc key1 :key2 (assoc key2 :key3 (conj key3 new-member))) Do I really have to assoc all the way through to the inner map? Isn't there a more succinct way to write this? In Common Lisp there's (setf (getf ...)) --~--~-~--~~~---~--~~ 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 could use assoc-in... (def rms (ref {:key1 {:key2 {:key3 #{)) (dosync (alter rms assoc-in [:key1 :key2 :key3] "foo")) {:key1 {:key2 {:key3 "foo"}}} Rgds, Adrian. On Sun, Jul 5, 2009 at 6:07 AM, Rowdy Rednose wrote: > > Say I have a data structure like this > > (def ref-map-map-map-set (ref {:key1 {:key2 {:key3 #{)) > > If I want to add a new member to the set which is the value of :key3, > I currently do this: > > (dosync > (let [key1 (:key1 @ref-map-map-map-set) > key2 (:key2 key1) > key3 (:key3 key2)] > (ref-set ref-map-map-map-set (assoc @ref-map-map-map-set :key1 > (assoc key1 :key2 (assoc key2 :key3 (conj key3 new-member))) > > Do I really have to assoc all the way through to the inner map? Isn't > there a more succinct way to write this? In Common Lisp there's (setf > (getf ...)) > > > --~--~-~--~~~---~--~~ 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
Rowdy, > Do I really have to assoc all the way through to the inner map? Isn't > there a more succinct way to write this? In Common Lisp there's (setf > (getf ...)) Remember, Clojure's data structures are immutable. You're not adding a value to a set -- what you're describing is (in Clojure) actually constructing a *new* set sharing the contents of the old, and putting it in three *new* nested maps (which might share contents with the existing maps), then setting the ref to point to the new outermost map. You'll find that after doing this the old values of each map and the set still exist, unchanged. If you no longer point to them, parts will be GCed. For this reason, you can't just walk the structures to the one you want to modify, then make the change. I'd probably write this as: (defn alter-it [new-member] (dosync (let [m @ref-map-map-map-set new-set (conj ((comp :key3 :key2 :key1) m) new-member)] (ref-set ref-map-map-map-set (assoc m :key1 (assoc (:key1 m) :key2 (assoc (:key2 m) :key3 new-set))) then get disgusted and write a macro to do it :) However, I'd point out that: * This might be a sign that you're doing things 'wrong'. * You could always use a ref in your map instead of a concrete set -- this basically gives you mutability. E.g., (def inner-set (ref #{})) (def ref-map-map-map-set (ref {:key1 {:key2 {:key3 inner-set}}})) (println @ref-map-map-map-set) (dosync (ref-set inner-set (conj @inner-set :foo-bar))) (println @ref-map-map-map-set) Hope that helps, -R --~--~-~--~~~---~--~~ 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
Much better! Thanks. On Jul 5, 1:20 pm, Adrian Cuthbertson wrote: > You could use assoc-in... > > (def rms (ref {:key1 {:key2 {:key3 #{)) > > (dosync (alter rms assoc-in [:key1 :key2 :key3] "foo")) > {:key1 {:key2 {:key3 "foo"}}} > > Rgds, Adrian. > > On Sun, Jul 5, 2009 at 6:07 AM, Rowdy Rednose wrote: > > > Say I have a data structure like this > > > (def ref-map-map-map-set (ref {:key1 {:key2 {:key3 #{)) > > > If I want to add a new member to the set which is the value of :key3, > > I currently do this: > > > (dosync > > (let [key1 (:key1 @ref-map-map-map-set) > > key2 (:key2 key1) > > key3 (:key3 key2)] > > (ref-set ref-map-map-map-set (assoc @ref-map-map-map-set :key1 > > (assoc key1 :key2 (assoc key2 :key3 (conj key3 new-member))) > > > Do I really have to assoc all the way through to the inner map? Isn't > > there a more succinct way to write this? In Common Lisp there's (setf > > (getf ...)) --~--~-~--~~~---~--~~ 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
On Jul 5, 1:23 pm, Richard Newman wrote: > However, I'd point out that: > > * This might be a sign that you're doing things 'wrong'. Could be. I'm still figuring out how to do things the functional way. The reason I have these nested maps is to give my data structure. I don't want to have a loose collection of things. It is easier to understand the hierarchical structure. Otoh you have to change the whole path up to the top of the hierarchy. > * You could always use a ref in your map instead of a concrete set -- That's right. I think I want to have a ref there anyway for another reason. --~--~-~--~~~---~--~~ 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
On Jul 5, 1:20 pm, Adrian Cuthbertson wrote: > (dosync (alter rms assoc-in [:key1 :key2 :key3] "foo")) > {:key1 {:key2 {:key3 "foo"}}} I just found update-in, which is even better, as I want to update a set: user=> (def gnu-rms (ref {:key1 {:key2 {:key3 #{)) #'user/gnu-rms user=> (dosync (alter gnu-rms update-in [:key1 :key2 :key3] #(conj % "foo"))) {:key1 {:key2 {:key3 #{"foo" --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---