Re: Why I'm getting StackoverflowError?
On Dec 5, 9:52 pm, HB hubaghd...@gmail.com wrote: Hi, I'm trying to write a function that calculates the length of a list: (defn list-length [col] (if col (+ 1 (list-length(rest col))) 0)) (list-length '(Java, Clojure, Scala)) Upon running it in the REPL, I got the error: java.lang.StackOverflowError (test.clj:3) What is going wrong? Unlike Common Lisp, the empty list is not a false value in Clojure, so your condition is always true. If you change your test to (if (empty? col) ... ), all should be good. Cheers, Danny. -- 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: One benefit of having a REPL
On Nov 28, 1:20 pm, John Harrop jharrop...@gmail.com wrote: One benefit of having a REPL: it makes regular expressions usable. So easy to test and tweak your RE compared to the traditional compile/test/debug cycle! I never even bothered with the java.util.regex package before Clojure as it was too painful to use. You just reminded me of a utility I wrote in Ruby some years ago to interactively build regular expressions. I hacked up a Clojure version in the past hour or so, and pushed it up to github at http://github.com/dannywoodz/regex-toolbox. Unfortunately, I can't claim to have come up with the idea, but implementing it was good fun. :-) Feedback always welcome! Cheers, Danny. -- 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: Deep deref
Danny, could you maybe hack up a possible very simple example of what you mean? snip I can not simply store a copy of the Karl person in Tinas :friends slot, because when Karl gets one year older, then I don‘t want to go through all persons, looking for Karls, and have their age updated. Hi André, Your shared instance constraint does make things a little more interesting than in my application, but I think John's suggestion about not storing friend instances directly is a good thing. If you were to instead assign an id to each created person, and have each friend list be a list of ids, the entity referred to by the id can still be immutable for a given dereference. Not sure how much sense that makes, so here's something crude that I've hacked up: (def *everyone* (ref {})) (def *global-id* (ref 0)) (defn next-id [] (dosync (commute *global-id* inc))) (defstruct person :name :friend-ids :id) (defn make-person [name] (struct person name [] (next-id))) (defn make-and-add-person [name] (let [person (make-person name)] (dosync (alter *everyone* assoc (:id person) person (defn befriend [person friend] (let [new-friend-list (conj (:friend-ids person) (:id friend)) new-person (assoc person :friend-ids new-friend-list)] (dosync (alter *everyone* assoc (:id person) new-person The 'down side' here is simply that you refer to people by ids, rather than directly, but the up side is that a given deref of *everyone* is immutable and consistent. Cheers, Danny. -- 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: Deep deref
André Thieme wrote: How can we handle this situation? Is it possible to implement a function “deep-deref” which works as blindingly fast as deref does? I find this very important, and this is of great practical relevance for me. Please share your ideas Hi André, I had a similar issue with an application I wrote a while back. The initial structure was simple: a grid-based map, containing a number of entities, each entity having a name, an owner, dimensions, etc. The map was behind a ref, and the entities were initially refs themselves, embedded within the map structure. Then I realised that it was difficult to know with certainty what was in the deref'd map. It kind of struck me then that I was thinking about the problem incorrectly. My object-oriented hat made me want to have the map and entities as separate things, each in charge of its own state. When I re-wrote the code so that the entities were themselves an immutable part of an immutable map, and that changes to entities resulted in an *entirely new map*, those problems went away. All the various interactions with the UI and with the network updated the map and entities transactionally, with a new, consistent map after each alteration. What a relief that was! In your case, adding someone to a friend list should result in what is conceptually a completely new database, that shares almost all of its structure with its predecessor. This top-level structure can sit behind a ref, with immutable person structs as constituent parts. This makes proper use of immutability and negates the need for a deep deref. That's just my experience. I'd be interested to know if anyone has an honest need for refs within refs (especially in a larger system). Cheers, Danny. -- 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: Beginner: performance of vector creation/modification
harto wrote: Hello, I've just started learning Clojure, so I'm trying to figure out the correct way of doing things. I've been trying to create and 'modify' a large vector for an online programming exercise, but I'm running into some performance issues. Any general tips would be appreciated! Well, I'm a beginner too, but I'll take a stab at answering your questions. Firstly, I'm creating a vector of booleans like this: (defn vector-of [n value] (vec (for [_ (range n)] value))) It takes quite a long time for large values of n, though: user= (time (dorun (vector-of 1e7 true))) Elapsed time: 6734.509528 msecs I suspect you're being bitten by the repeated creation of the underlying data structures. 'range' is going to create a lazy sequence, from which 'for' is going to create its own, lazy structure, which 'vec' then iterates over to create its own. Just running '(time (dorun (range 1e7)))' shows that it's taking up a non-trivial amount of time just on its own. This modified version does the same thing a little more quickly: (defn vector-of [n value] (loop [v [] c 0] (if ( c n) (recur (assoc v c value) (inc c) user (time (dorun (vector-of 1e7 true))) Elapsed time: 1000.409039 msecs Secondly, I'm iterating across one of these large vectors using something like the following (contrived) function: (defn set-flags [v] (loop [i 0 v v] (if ( i (count v)) (recur (inc i) (assoc v i false)) v))) user= (let [v (vector-of 1e7 true)] (time (dorun (set-flags v Elapsed time: 15563.916114 msecs Am I missing anything obvious here? That seems like a really long time to me. With the modified vector-of, above, this problem seems to go away for me: user (time (dorun (set-flags (vector-of 1e7 true Elapsed time: 1009.362723 msecs Cheers, Danny. --~--~-~--~~~---~--~~ 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: Beginner: performance of vector creation/modification
Strangely, I'm not seeing my own emails turn up in this list... Anyways, after re-reading what I sent, it only partially applies :-) The obvious (deliberate, of course) mistake with my vector-of was that I didn't return the vector that I'd built up! So set-flags was, of course, rather fast in dealing with nil. Oops. So the (kind of proper) implementation would be: (defn vector-of [n value] (loop [v [] c 0] (if ( c n) (recur (assoc v c value) (inc c)) v))) The only thing that I can see that would speed up set-flags would be to not take the length of the vector on every iteration: I suspect that may involve a traversal of the vector every time it's called. Cheers, Danny. On 19/10/2009 13:37, Stuart Campbell wrote: 2009/10/19 Danny Woods dannywo...@gmail.com mailto:dannywo...@gmail.com harto wrote: Hello, I've just started learning Clojure, so I'm trying to figure out the correct way of doing things. I've been trying to create and 'modify' a large vector for an online programming exercise, but I'm running into some performance issues. Any general tips would be appreciated! Well, I'm a beginner too, but I'll take a stab at answering your questions. Firstly, I'm creating a vector of booleans like this: (defn vector-of [n value] (vec (for [_ (range n)] value))) It takes quite a long time for large values of n, though: user= (time (dorun (vector-of 1e7 true))) Elapsed time: 6734.509528 msecs I suspect you're being bitten by the repeated creation of the underlying data structures. 'range' is going to create a lazy sequence, from which 'for' is going to create its own, lazy structure, which 'vec' then iterates over to create its own. Just running '(time (dorun (range 1e7)))' shows that it's taking up a non-trivial amount of time just on its own. Ah, OK. I didn't understand the implications of using those lazy sequences. I think I need to do some more reading on lazy data structures. Thanks for your input! This modified version does the same thing a little more quickly: (defn vector-of [n value] (loop [v [] c 0] (if ( c n) (recur (assoc v c value) (inc c) user (time (dorun (vector-of 1e7 true))) Elapsed time: 1000.409039 msecs Secondly, I'm iterating across one of these large vectors using something like the following (contrived) function: (defn set-flags [v] (loop [i 0 v v] (if ( i (count v)) (recur (inc i) (assoc v i false)) v))) user= (let [v (vector-of 1e7 true)] (time (dorun (set-flags v Elapsed time: 15563.916114 msecs Am I missing anything obvious here? That seems like a really long time to me. With the modified vector-of, above, this problem seems to go away for me: user (time (dorun (set-flags (vector-of 1e7 true Elapsed time: 1009.362723 msecs Cheers, Danny. --~--~-~--~~~---~--~~ 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: Proposal: New Reader Macro #s{ ... }
Perl and Ruby do something similar with regular expressions, where the character following 'm' or 's' becomes the delimiter for that expression, making 'm/\/some\/path/' identical to 'm!/some/path!'. The delimeter can be 'smart' as well, where the closing delimiter is dependent upon the opening one (in the case of brackets, parentheses and braces) leading to expressions like 'm(/some/path)'. It would be really handy if Clojure had a similar #s!!, #s(), #s//, etc. facility. John Harrop wrote: How about borrowing a page from LaTeX? That has a \verb+text+ which can use any desired delimiter character. My thought is to have something like $+.+ turning whatever was between the character following $ (here, +) until the next occurrence of that character into a literal string. A way to escape the chosen character is still desirable, though it could be chosen in most cases not to be needed. Perhaps the sequence $+ recurring would translate to a literal + (and any other $x digraph into a literal $x digraph). $ seems like a good choice because it suggests the letter s, as in string, is not already overloaded in Clojure for some following symbols (unlike #), and very rarely occurs in text with a nonwhitespace character afterward. (This post stands as an obvious exception, but even then, I've used $+ and $x only so using a third nonwhitespace character after the $ would allow quoting this post verbatim in the same manner.) Sole limitation on the following character would be that it not be whitespace (a stand-alone $ would be treated the same as it currently is, as would a $ with no leading whitespace, so referencing nested Java classes would not be broken; multicharacter symbols starting with $ would be but I expect there is as of yet little or no preexisting code with such symbols). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: What books have helped you wrap your brain around FP and Clojure?
+1 for Higher Order Perl. The author, Mark Jason Dominus, has made the book available for free download at http://hop.perl.plover.com/book/. Cheers, Danny. --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---