Re: Synchronous watches
On Feb 27, 8:57 am, Rich Hickey richhic...@gmail.com wrote: I've added (back) synchronous watches (svn 1309+), which used to exist for agents, now for all reference types. [...] Please try them out for your latest Cells-like and other reactive programs. I'd like to move this out of the experimental category. Feedback and questions welcome I hope this works out well. I've folded it into my app, and am finding it useful. They facilitate factoring out application state into a repository object whose sole job is to keep track of such state; I can use watches to pass updated state to a synch agent that periodically writes the changed state to a store, or to a UI agent that updates views. That makes for a nice decomposition of concerns. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Opinions on - macro? (was Re: Extensive use of let?)
Hi, Am 01.03.2009 um 02:19 schrieb Belfabius: I quickly learned the - macro can't be used in the same way for one simple reason; the value that is threaded through to the forms is always placed in the first argument position. How about adding a macro -- it could be called | just as in F# -- that places the value in the last argument position? (It's dead simple to write -- I just copied and modified the - macro.) See here for a in-depth discussion of the pipe macro. :) http://groups.google.com/group/clojure/browse_frm/thread/66ff0b89229be894/c3d4a6dae45d4852 Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: time complexity for immutable priority queue?
Hi, that's a nice example of using closures to store data! (f)first and rest look like constant time to me. count is linear time, but could easily be made constant time by storing the counts instead of recursing. Insertion is linear time though, plus it recurses, resulting in stack sizes in the order of the length of the queue. Here's a version that's roughly equivalent (including the recursion problem), but uses maps instead of closures: (defn prio-insert [queue elem prio] (if ( prio (:prio queue (Integer/MIN_VALUE))) {:first elem :prio prio :count (inc (:count queue 0)) :rest queue} (let [new-rest (prio-insert (:rest queue) elem prio)] (assoc queue :rest new-rest :count (inc (:count new-rest)) user= (def pq (prio-insert nil 3 4)) #'user/pq user= pq {:first 3, :prio 4, :count 1, :rest nil} user= (def pq (prio-insert pq 2 10)) #'user/pq user= pq {:first 2, :prio 10, :count 2, :rest {:first 3, :prio 4, :count 1, :rest nil}} user= (def pq (prio-insert pq 4 1)) #'user/pq user= pq {:first 2, :prio 10, :count 3, :rest {:first 3, :prio 4, :count 2, :rest {:first 4, :prio 1, :count 1, :rest nil}}} user= (:first (:rest pq)) 3 Kind regards, achim Am 01.03.2009 um 06:31 schrieb zoglma...@gmail.com: After helping tutor some students earlier in the week on the subject of priority queues, I ended up implementing it in Clojure as a mutable data structure. It was straight forward, but curiosity struck and I implemented the priority queue as an immutable data structure. I'm pretty sure that 'ffirst 'first 'count and 'rest have a constant time complexity, but it is a little hard to wrap my mind around this code. Is it really constant time? ;- immutiable priority queue - (defn priority-cons [priority data queue] (defstruct element :priority :data) (let [elem (struct element priority data) queue-first (if (nil? queue) nil (queue 'ffirst)) queue-rest (cond (nil? queue) nil (nil? elem) (queue 'rest) (= priority (queue-first :priority)) queue :else (priority-cons priority data (queue 'rest)))] (fn [op] (cond (= op 'count) (cond (nil? queue) 1 (nil? elem) (queue 'count) :else (inc (queue 'count))) (= op 'first) (cond (nil? queue) data (nil? elem) nil (= priority (queue-first :priority)) data :else (queue-first :data)) (= op 'ffirst) (cond (nil? queue) elem (nil? elem) nil (= priority (queue-first :priority)) elem :else queue-first) (= op 'rest) queue-rest ;--- testing code (defn print-priority-queue [queue] (loop [queue queue] (if (nil? queue) nil (do (println (queue 'first)) (recur (queue 'rest)) (def a (priority-cons 10 hello nil)) (print-priority-queue a) (a 'count) (def b (priority-cons 20 hello2 a)) (print-priority-queue b) (b 'count) (def c (priority-cons 15 hello-m b)) (print-priority-queue c) (c 'count) ((c 'rest) 'count) (((c 'rest) 'rest) 'first) (((c 'rest) 'rest) 'count) (((c 'rest) 'rest) 'rest) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Opinions on - macro?
Meikel and eyeris, Thanks, that clarifies the usage of - even multiple parameters. IMHO, - simplifies things where unary functions are involved and where the list-parens are absent, so that - creates the list. In the other cases, the standard syntax is easier on the eye. Joshua On Sun, Mar 1, 2009 at 12:17 AM, eyeris drewpvo...@gmail.com wrote: You are wrong. Many writings use ,, as a place-holder for where - is placing the argument. Take Meikel's example above: (foo (bar (baz (frobnicate a-thing)) bla)) Becomes (- a-thing frobnicate baz (bar bla) foo) So bar is a function of more than one argument. Re-written with place- holders it would be: (- a-thing (frobnicate ,,) (baz ,,) (bar ,, bla) (foo ,,)) Does that make it more clear? -Drew On Feb 28, 9:39 pm, Joshua Fox joshuat...@gmail.com wrote: - confuses me: Does it treat functions with multiple parameters different from functions with one parameter? Am I right that it can only be used with the latter? Joshua --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure + Terracotta = Yeah, Baby!
I've started work on a Terracotta Integration Module for Clojure already. As I understand it, we can package up the Terracotta config as well as any replacement classes. This way we can patch Clojure temporarily until either Terracotta supports the features we need, or Clojure can be rewritten so that it doesn't use classes that are unsupported by Terracotta (if prudent and possible), and there would be no need to fracture the Clojure code base. I'll keep everyone apprised of my progress. Paul On Sat, Feb 28, 2009 at 11:35 PM, Nabib El-Rahman nabi...@gmail.com wrote: Its a way to package integration details into a module. For example, if I want to cluster EHCache, I can drive through the code and figure out what data structure to share and subsequently lock on. All that work can be packaged into a module for terracotta, so that way people who just want to use ehcache + terracotta change just include tim-ehache in terracotta configuration and that's it. the same can be done for clojure. the details can be abstract to a tim-clojure. http://www.terracotta.org/web/display/docs/Terracotta+Integration+Modules+Manual -Nabib On Sat, Feb 28, 2009 at 8:16 PM, hank williams hank...@gmail.com wroote: Writing a TIM is definitely the way to go, It's a place to hide the glue until both Terracotta and Clojure catches up with each other. uhhh what is a TIM? Thanks Hank -- blog: whydoeseverythingsuck.com --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
could someone explain the difference between these two error messages
Playing with readFileToByteArray in the repl: user= (import '(org.apache.commons.io FileUtils)) nil user= (def dawg (FileUtils/readFileToByteArray words.dawg)) java.lang.ClassCastException (NO_SOURCE_FILE:10) user= (FileUtils/readFileToByteArray words.dawg) java.lang.ClassCastException: java.lang.String cannot be cast to java.io.File (NO_SOURCE_FILE:0) The second error message was a lot more helpful than the first - why was the message lost en route? It doesn't always happen: user= (/ 1 0) java.lang.ArithmeticException: Divide by zero (NO_SOURCE_FILE:0) user= (def a (/ 1 0)) java.lang.ArithmeticException: Divide by zero (NO_SOURCE_FILE:18) martin --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: (rest ())
On Feb 28, 2009, at 5:45 PM, Mark Engelberg wrote: As Rich explained in one post, in Lisp-like languages, there is a certain amount of intertwining between two views of a sequence which is a series of linked nodes. One way is to think about these nodes as just nodes with a first and rest. Another way is to think about each node as representing an entire chain from this node onward to the end. He explained that next is more like the move from one node to another view, and rest is more like the view of these things as collections, where rest gives you the collection of everything but the first. (rest []) translates in my mind to everything but the first item of []. There is no first item of [], and there isn't an everything-but-the-first-item of it. It's empty. You can't take something out of it. One way to think of it is as the sequence version of: ;a set of the things other than first (disj #{} first) = #{} ;a sequence of the things other than first (rest ()) = () i.e. it's an empty container of a particular type. Rich --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: If/cond thoughts..
On Feb 25, 10:19 pm, glow glo...@gmail.com wrote: Hi everyone! I am currently learning Lisp and Clojure. A few days ago i read how if in Arc works and I wonder why it is not the same in Clojure: (if a b ; if a then b c d ; elseif c then d e) ; else e. (cond pred1 form1 pred2 form2 :else form3) seems pretty good to me. I prefer that to the Arc code above. Gavin --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure Continuous Integration on Tapestry360
If I want to install maven into my local repository from a working copy (with local changes), how would I do so? I would expect to be able to do mvn install, but it does not work. The pom.xml has been gutted of any source directory definitions, so it only builds an empty JAR. Assuming I have the maven-ant-tasks library installed, is there an ant task to install to my local repo? Paul On Feb 22, 12:48 pm, Howard Lewis Ship hls...@gmail.com wrote: I've set up two Clojure builds on the Tapestry360 Continuous Integration Site: http://tapestry.formos.com/bamboo A trunk build runs after any changes to clojure. The nightly build runs every morning. Clojure now producesMavenartifacts in thehttp://tapestry.formos.com/maven-snapshot-repositoryMavenrepository as part of the nightly build. To access the nightly snapshot inMaven, you must update your pom.xml's repositories element (creating it as necessary): repositories repository idtapestry-snapshots/id urlhttp://tapestry.formos.com/maven-snapshot-repository//url /repository /respositories You can then add a dependency for Clojure: dependency groupIdorg.clojure/groupId artifactIdclojure-lang/artifactId version1.0-SNAPSHOT/version /dependency Note that the repository includes a sources JAR (most IDEs will download it automatically, which may help with debugging). In addition, there's a slim variant, where the core library Clojure sources are NOT pre-compiled: dependency groupIdorg.clojure/groupId artifactIdclojure-lang/artifactId version1.0-SNAPSHOT/version classifierslim/classifier /dependency The slim JAR is about half the size of the standard JAR but will, obviously, start up more slowly as all the scripts need to be compiled at runtime. I'd be interested in setting up the same thing for the Clojure contrib library ... we can set it up as a dependent build of Clojure, so that any change to Clojure forces a rebuild of contrib. -- Howard M. Lewis Ship Creator Apache Tapestry and Apache HiveMind --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: If/cond thoughts..
Thanks everyone for the response! As a Lisp newbie i may sound naive but: 1) Why is cond and condp syntax inconsistent (necessity of :else)? 2) On page 1 of introduction to Lisp I read (+ 1 2) but also (+ 1 2 3). Wow prefix notation is cool. But imagine for a moment that in an new exciting language you can write (* 1 2) but not (* 1 2 3)! You must use (cond* 1 2 3 4) and what is worse (cond* 1 2 3 4 :else 5)! Moreover since :else is necessary in cond why not (if a b :else c)?! That looks sooo bad. 3) That Arc syntax is not colliding with current well known cond and if (maybe except of the possibility of catching some arity exceptions). Who is used to them might still use traditional syntax and new players might prefer Arc's (and I believe they would). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: If/cond thoughts..
Hi, Am 01.03.2009 um 15:23 schrieb glow: 1) Why is cond and condp syntax inconsistent (necessity of :else)? The syntax of cond is (cond test1 clause1 test2 clause2 ...) That is the first argument will be evaluated. If it is logically true, the second argument is evaluated and its result returned. If the test is logically false, cond goes on with test2 and clause2 etc. :else is simply a trick to provide an always true test. You could also write true, 5 or Hello World! instead of :else. This is the same eg. in Scheme. The syntax of condp is (condp test-fn thing candidate1 clause1 candidate2 clause2 ...) Here the first and second arguments are a test function and the thing to test. condp takes the third argument and checks, whether (test-fn candidate1 thing) returns logically true. If so clause1 is evaluated and its result returned. Otherwise it goes on with candidate2 and clause2. How do you specify here the :else? So the convention is an odd clause at the end, which is then interpreted at as else-clause if no candidate yields logically true. Every syntax by itself is consistent. Although the :else could be considered a hack. Maybe cond should be adjusted to allow an odd else-clause? Note also, that condp throws if no candidate yields true and no else-clause is provided. And it supports a form, where the test-fn result is passed to the clause which is expected to be a function. (condp some coll set1 : (fn [hit] ...) set2 : (fn [hit] ...) ...) 2) On page 1 of introduction to Lisp I read (+ 1 2) but also (+ 1 2 3). Wow prefix notation is cool. But imagine for a moment that in an new exciting language you can write (* 1 2) but not (* 1 2 3)! You must use (cond* 1 2 3 4) and what is worse (cond* 1 2 3 4 :else 5)! Moreover since :else is necessary in cond why not (if a b :else c)?! That looks sooo bad. The reasons why it is like that are outlined above. And for the case file: In almost all languages you cannot say (* 1 2 3). You have to say (* (* 1 2) 3) aka 1 * 2 * 3. Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: new Clojure article
Looks very nice. I like the code to text ratio, it's denser than most texts that I see of this nature. Great job! On Feb 28, 1:27 pm, Mark Volkmann r.mark.volkm...@gmail.com wrote: I've written anarticleonClojure. Seehttp://ociweb.com/jnb/jnbMar2009.html. The goal of thisarticleis to provide a fairly comprehensive introduction to theClojureprogramming language. A large number of features are covered, each in a fairly brief manner. Check out the hyperlinked table of contents. Thanks to all of you that have patiently answered my questions aboutClojureover that past couple of months! While reading this, if you spot errors or just have ideas for better ways to explain certain concepts, please email me. I plan to make updates to thearticlefrequently in order to make it as valuable a resource as possible. -- R. Mark Volkmann Object Computing, Inc. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Synchronous watches
On Feb 27, 9:57 am, Rich Hickey richhic...@gmail.com wrote: I've added (back) synchronous watches (svn 1309+), which used to exist for agents, now for all reference types. Cool. I won't have much time to play with this until next week, but I look forward to experimenting with it. -Stuart Sierra --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
updated cfa
I've updated cfa.clj (original thread: http://groups.google.com/group/clojure/browse_frm/thread/ce795dd1fb646df1/e211230f5e230bc5?lnk=gstq=cfa#e211230f5e230bc5) in the user files for SVN 1315, also many changes to (hopefully) use more idiomatic code. Comments welcome. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: functional programming idiom
On Feb 28, 6:16 pm, linh nguyenlinh.m...@gmail.com wrote: hello, what's the common idiom in functional programming regarding checking the validity of arguments to functions. i think this is called defensive programming vs contract programming. Mostly defensive, I think. Some languages (e.g. PLT Scheme) have contracts: http://docs.plt-scheme.org/guide/contracts.html There's a new tech report on contract checking for Haskell that might be interesting too -- I've just started reading it: www.cl.cam.ac.uk/techreports/UCAM-CL-TR-737.pdf Regards, -- Michel S. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: functional programming idiom
On Mar 1, 11:02 am, Michel S. michel.syl...@gmail.com wrote: On Feb 28, 6:16 pm, linh nguyenlinh.m...@gmail.com wrote: hello, what's the common idiom in functional programming regarding checking the validity of arguments to functions. i think this is called defensive programming vs contract programming. Mostly defensive, I think. Some languages (e.g. PLT Scheme) have contracts:http://docs.plt-scheme.org/guide/contracts.html Also, constructs such as Haskell's Maybe monad (available in clojure- contrib) simplifies doing defensive programming on a chain of computation. Which reminds me. We have no error monad yet (not as important since Clojure has Java exceptions, though). -- Michel S. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Utility / Reflection functions
I'm trying to get back into using Clojure a bit. This time around with actual package management and builds, so that I'm able to easily import Java classes and build a Windows / Linux / Mac OS X application in a single step. However, I'll freely admit that I'm a Java newbie. I get the basic gist of the language, but find myself stalling when it comes to finding methods and fields on an object. One thing that I found myself missing, deeply, was an equivalent to Python's dir function, but for Java objects. Essentially, I wanted a set of functions that would let me list and search through methods, constructors and fields on a Java object. So I set up a few and dropped them in ~/.cljrc (My shell scripts to launch Clojure load this, so it's a handy place to put reader functions. ===.cljrc (in-ns 'user) (import '(java.util.regex Pattern Matcher) '(java.lang.reflect Modifier)) (defn #^{:doc Takes a sequence of strings as arguments and joins them with the string `ch'. If `ch' is omitted, a space (\ \) will be used. If only one string is supplied, it will be returned unchanged. If no strings are supplied, an empty string (\\) is returned. :test (fn [] (assert (= (join-strings nil))) (assert (= a (join-strings '(a (assert (= a1b (join-strings 1 (list a b (assert (= a b c (join-strings [a b c] } join-strings ([strings] (join-strings strings)) ([ch strings] (let [strings (seq strings)] (if (empty? strings) (if (= (.size strings) 1) (reduce str strings) (reduce (fn [a b] (str a ch b)) strings)) (defn #^{:doc Takes as arguments a regular expression and a list. Returns the elements of the list for which the regular expression is a match. The comparison is done against (str element), but the returned values are the actual elements. The optional `prefix' argument is passed as a prefix to all elements in `li', but the elements are returned without the prefix.} filter-list-by-re ([] nil) ([li] li) ([re li] (filter-list-by-re re li)) ([re prefix li] (let [regex (. Pattern (compile re (. Pattern CASE_INSENSITIVE)))] (filter (fn [x] (.. regex (matcher (str prefix x)) (find))) li (defn #^{:doc Returns a listing of the methods, constructors and fields of an object as a hashmap.} dir ([ob] (let [methods (.. ob (getClass) (getMethods)) constructors (.. ob (getClass) (getConstructors)) fields (.. ob (getClass) (getFields))] (hash-map method (seq methods) constructor (seq constructors) field (seq fields ([re ob] (let [old-map (dir ob)] (reduce merge (map (fn [key] (hash-map key (filter-list-by-re re key (get old-map key nil (keys old-map)) (defn #^{:doc Tests if the object `ob' has a method with the name `method-name'. Returns true if yes, false otherwise. :test (fn [] (assert (has-method? size (list 1))) (assert (not (has-method? ize (list 1)} has-method? [method-name ob] ( 0 (.size (get (dir (str \\W method-name \\() ob) method (defn #^{:doc Returns the methods, constructors and fields on an object as a single list. } list-dir ([ob] (list-dir ob)) ([re ob] (reduce concat (vals (dir re ob) (defn #^{:doc Prints the methods, constructors and fields on an object, one per line. If the optional `re' option is specified, only methods matching that regular expression will be printed. Note that the regular expression is case insensitive and can match the prefixes, so (print-dir \^field\ \\) will match only fields for the String class } print-dir ([ob] (print-dir ob)) ([re ob] (let [old-map (dir re ob)] (println (join-strings \n (mapcat (fn [key] (map (fn [val] (str key : val)) (get old-map key))) (keys old-map))) (defn #^{:doc Prints fields of `ob', one per line, showing field name and value. If the optional argument `re' is supplied, only fields matching that regular expression are printed.} print-fields ([ob] (print-fields ob)) ([re ob] (let [fields (get (dir re ob) field)] (println (join-strings \n (map (fn [field] (join-strings (list (. Modifier (toString (. field
Re: Clojure + Terracotta = Yeah, Baby!
We will go for a TIM. Just looked at the doc and tes that would simplify our work a lot. Thank you, Luc On Sat, 2009-02-28 at 18:48 -0800, Nabib El-Rahman wrote: Hi guys, I work for Terracotta ( on the server side ) and find this work with Clojure + Terracotta very exciting. Writing a TIM is definitely the way to go, It's a place to hide the glue until both Terracotta and Clojure catches up with each other. If you have any questions feel free to post on our forums http://forums.terracotta.org/forums/forums/list.page If you check out our trunk version, theres also an effort to make a common-api which will help writing a TIM easier for you guys. Good luck! -Nabib On Sat, Feb 28, 2009 at 12:02 PM, Luc Prefontane lprefonta...@softaddicts.ca wrote: We think the same way. Our first implementation of an alternative to AtomicReference is straightforward, we will look at improving it if the need arises. It will be easier to do so when we get stats from Terracotta after running some benchmarks. There's much to do before getting there. Luc On Sat, 2009-02-28 at 14:33 -0500, Paul Stadig wrote: In the Namespace case, it might be premature optimization to worry about AtomicReference being replaced. If there is a way to rewrite that code with, say, synchronized blocks, and it will work better with Terracotta, I think it would be worth doing. I don't think it would be normal usage to be updating the mappings and aliases in a namespace 1,000 times a second. AtomicReference is also used in Atom and Agent. Those cases may not be as straight forward. Paul On Sat, Feb 28, 2009 at 11:51 AM, Luc Prefontaine lprefonta...@softaddicts.ca wrote: 1) AtomicReference is used in several places. Instead of changing it, we think we can keep it when Clojure runs locally and provide an alternative when running in shared mode. AtomicReference is optimized to be efficient in a standalone JVM. We would like to keep it that way. Eventually Terracotta will provide instrumentation on this class by default so the shared implementation could be thrown away in the near future. We see the double implementations as a transition period until Terracotta supports it directly. 2) Noted Shared versus local mode: That's what we have in mind, getting Clojure to work in a shared mode versus a local/standalone mode. We want 0 impacts on the user code. Eventually we could use meta data to provide some hints that would allow us to fine tune shared interactions from user code. This would not impact local mode behaviours. We're not there yet but we know that this possibility exists so that's reassuring for the future. Integration is pretty simple once the common code base integrates the necessary changes. We need a shell script, a Terracotta configuration that will be maintained as part of the Clojure code base and some documentation. As of now we use a system property to toggle the modes, we will implement a transparent way (testing the presence of a terracotta property most probably). Luc -- Luc Préfontaine Off.:(514) 993-0320 Fax.:(514) 993-0325 Armageddon was yesterday, today we have a real problem... -- Luc Préfontaine Off.:(514) 993-0320 Fax.:(514) 993-0325 Armageddon was yesterday, today we have a real problem... --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Early registration for International Lisp Conference (Cambridge, MA, 22-25 March 2009)
Anyone know if they will be filming the ILC 2009? I can't fly to Boston, but I'd pay to get a quality stream. -Jeff Stephen C. Gilardi wrote: Rich will be presenting a Clojure in Depth tutorial session on Sunday, 22 March 2009 at the International Lisp Conference taking place at MIT in Cambridge, MA: http://www.international-lisp-conference.org/2009/tutorials#clojure It's scheduled in 3 parts for a total of 5 hours: http://www.international-lisp-conference.org/2009/schedule The conference agenda contains a lot more interesting Lisp-related content as well: http://www.international-lisp-conference.org/2009/index I'm writing to mention this today because the early registration deadline is nearly upon us. The conference fee for an individual participant is $210 on or before 1 March 2009 and rises to $250 after that: http://www.regonline.com/builder/site/Default.aspx?eventid=688757 If you've been on the fence about attending, now is a good time to conclude: There's no way I'm missing that! Cheers, --Steve --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: functional programming idiom
thank you for the information On Mar 1, 5:09 pm, Michel S. michel.syl...@gmail.com wrote: On Mar 1, 11:02 am, Michel S. michel.syl...@gmail.com wrote: On Feb 28, 6:16 pm, linh nguyenlinh.m...@gmail.com wrote: hello, what's the common idiom in functional programming regarding checking the validity of arguments to functions. i think this is called defensive programming vs contract programming. Mostly defensive, I think. Some languages (e.g. PLT Scheme) have contracts:http://docs.plt-scheme.org/guide/contracts.html Also, constructs such as Haskell's Maybe monad (available in clojure- contrib) simplifies doing defensive programming on a chain of computation. Which reminds me. We have no error monad yet (not as important since Clojure has Java exceptions, though). -- Michel S. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
IntelliJ Clojure Plugin - Minor Indentation Issues.
After using La Clojure a bit more, I noticed a few minor issues with the indentation system. Inside a let form binding, the next line should be indented to one character past the opening bracket. eg. should be like: (let [i hi j hi]) where j lines up with i. current behavior: (let [i hi j hi]) where j lines up with [ Also Nested forms, IMO, should be indented to be two spaces past the last opening parenthesis. eg. should be like: (let [i (fn [a] (println a))] current behavior: (let [i (fn [a] (fn [a] (println a)))] Those are the only two issues I've noticed so far. Everything else is working perfectly. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Making agents able to temporarily yield place on thread pool
Hi all, My concurrent dabblings in Clojure have been a real pleasure so far. In terms of concurrency, it's just in a completely different league from any other language I've tried. However, I think agents could be made even more friendly by allowing them to temporarily surrender their place in the thread pool pending another computation. Specifically, I'm thinking of a function 'yield' called as (yield other-agent msg-fn args) from within agent actions. If agent a yields to agent b, a gets off the thread pool and msg is sent to b with given args. When b finishes executing the message, the yield call returns b's new value, and a gets back on the thread pool. I _think_ the language could prevent deadlocks by: - making agents not take any messages while they are 'yielded' - keeping a 'yield stack' and checking that no cycles happen. Here are two use cases for yield: 1) Say an 'auto-agent' cell needs to run an expensive, parallelizable computation to update its value. Without yield you could do this by dispatching the action with send-off, or by splitting the cell up into multiple cells, each handling a chunk of the computation. Yield would be nicer than both: send-off spawns an expensive kernel thread (as I understand it) and breaking up the cell complicates the dataflow model unnecessarily. 2) Currently this program, which creates a tree of dependent futures, deadlocks on my 8-core mac pro: (def breadth 4) (defn with-deref [fun] (fn [ x] (apply fun (map deref x (defn future-tree [depth] (if (= depth 0) (future 1) (let [new-futures (map future-tree (repeat breadth (- depth 1)))] (future (apply (with-deref +) new-futures) ; WARNING: This deadlocks on 8-core Mac Pro! (future-tree 4) I'm guessing it deadlocks because the thread pool fills up with futures that aren't ready to go, but it feels like the language should be able to avoid the deadlock without requiring the programmer to think about how many threads are actually in the thread pool. If futures were based on agents, which yielded when deref-ing other futures, the deadlock wouldn't happen. I have no idea how hard it would be to implement yield, as I have very little practice with Java. Thoughts? Anand --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: functional programming idiom
On Mar 1, 12:19 pm, linh nguyenlinh.m...@gmail.com wrote: thank you for the information On Mar 1, 5:09 pm, Michel S. michel.syl...@gmail.com wrote: On Mar 1, 11:02 am, Michel S. michel.syl...@gmail.com wrote: On Feb 28, 6:16 pm, linh nguyenlinh.m...@gmail.com wrote: hello, what's the common idiom in functional programming regarding checking the validity of arguments to functions. i think this is called defensive programming vs contract programming. Mostly defensive, I think. Some languages (e.g. PLT Scheme) have contracts:http://docs.plt-scheme.org/guide/contracts.html Also, constructs such as Haskell's Maybe monad (available in clojure- contrib) simplifies doing defensive programming on a chain of computation. Which reminds me. We have no error monad yet (not as important since Clojure has Java exceptions, though). -- Michel S. Good that you brought this up. I was considering of writing more design by contract code. It is definitely a good coding style --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
[PATCH] Getting substrings counting from the end
Phil Hagelberg p...@hagelb.org writes: It's a pretty common idiom in other languages for substring functions to count from the end if given a negative index. (substring hello world! 6 -1) ;; = world I'd be glad if Clojure's subs function could work like this. Should I create an issue and patch to implement it? Haven't heard any response on this positive or negative. Here's the new function definition: (defn subs Returns the substring of s beginning at start inclusive, and ending at end (defaults to length of string), exclusive. Negative arguments count from the end. ([#^String s start] (subs s start (count s))) ([#^String s start end] (let [count-back #(if ( 0 %) (+ (count s) %) %)] (.substring s (count-back start) (count-back end) Am I the only one who finds this useful? Perhaps if it's not suited for core it could go in str-utils in contrib as substring. Thoughts? -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 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 -~--~~~~--~~--~--~---
Internal structure of evaluation results
Every now and again I try to get serious about learning Clojure and every time I quit due to its documentation. I find it confusing. Nothing seems to be where it should be, there are almost no examples etc. So, every time I end up writing (in Java, I might add) a documentation browser with index, full-text search support, bookmarks (something similar to Eclipses help system or kchmviewer) and maybe a possibility of adding custom examples to meta :doc with aspiration of building a personal tutorial as I go along. I can't seem to find a way of obtaining that information from Clojures runtime in a standard manner, however. I tried tackling the 'problem' with evaluating a (map meta (reduce concat (map vals (map ns- publics (all-ns) and then parsing the result using Clojures java classes. I can do that without major problems. But I'm tired of doing it every time when some (sub)results type gets changed (the last one was from LazyCons to LazySeq) and I naively update everything from the SVN. Is there any guarantee with regard to the internal structure of evaluation results (speaking in Java terms)? If not, is there something planed to that effect for official release(s)? Alternatively, what's the best (quickest, most robust, ...) way of obtaining Clojures runtime info in a manner similar to this: MapString, interns // keys == distinct namespace names interns: MapString, meta // keys == distinct intern or public names meta: MapString, String (or MapString, ListString for the sake of arguments ;-) ) // keys == meta names in a sentence: something that could be parsed from within Java using java.lang.String and Java collection classes? Regards, David --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: [PATCH] Getting substrings counting from the end
On Sun, Mar 1, 2009 at 2:13 PM, Phil Hagelberg p...@hagelb.org wrote: Phil Hagelberg p...@hagelb.org writes: It's a pretty common idiom in other languages for substring functions to count from the end if given a negative index. (substring hello world! 6 -1) ;; = world I'd be glad if Clojure's subs function could work like this. Should I create an issue and patch to implement it? Haven't heard any response on this positive or negative. Here's the new function definition: (defn subs Returns the substring of s beginning at start inclusive, and ending at end (defaults to length of string), exclusive. Negative arguments count from the end. ([#^String s start] (subs s start (count s))) ([#^String s start end] (let [count-back #(if ( 0 %) (+ (count s) %) %)] (.substring s (count-back start) (count-back end) Am I the only one who finds this useful? Perhaps if it's not suited for core it could go in str-utils in contrib as substring. Thoughts? I'd like to see it added. I'm used to having that available in Ruby. -- R. Mark Volkmann Object Computing, Inc. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: [PATCH] Getting substrings counting from the end
On Sun, Mar 1, 2009 at 10:13 PM, Phil Hagelberg p...@hagelb.org wrote: Phil Hagelberg p...@hagelb.org writes: It's a pretty common idiom in other languages for substring functions to count from the end if given a negative index. (substring hello world! 6 -1) ;; = world I'd be glad if Clojure's subs function could work like this. Should I create an issue and patch to implement it? Haven't heard any response on this positive or negative. Here's the new function definition: (defn subs Returns the substring of s beginning at start inclusive, and ending at end (defaults to length of string), exclusive. Negative arguments count from the end. ([#^String s start] (subs s start (count s))) ([#^String s start end] (let [count-back #(if ( 0 %) (+ (count s) %) %)] (.substring s (count-back start) (count-back end) Am I the only one who finds this useful? Perhaps if it's not suited for core it could go in str-utils in contrib as substring. Makes sense to me, but there's a bug in your function. You want ( % 0) instead of ( 0 %). -- Michael Wood esiot...@gmail.com --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Internal structure of evaluation results
I find it confusing. Nothing seems to be where it should be, there are almost no examples Just my opinion, but I think that Clojure is very well documented, both on clojure.org and on various online articles. But I'm tired of doing it every time when some (sub)results type gets changed In good encapsulated fashion, Clojure guarantees the interface of its returned objects, but not the implementation class to its documentation How about doc and find-doc user= (doc +) user= (find-doc vec) ... namespace names ...distinct intern or public names Take a look at fnuctions mentioned here http://clojure.org/namespaces like ns-name http://clojure.org/api#ns-name ns-aliaseshttp://clojure.org/api#ns-aliases ns-imports http://clojure.org/api#ns-imports ns-internshttp://clojure.org/api#ns-interns ns-map http://clojure.org/api#ns-map ns-publicshttp://clojure.org/api#ns-publics ns-refers http://clojure.org/api#ns-refers Joshua On Sun, Mar 1, 2009 at 10:15 PM, David david.ra...@gmail.com wrote: Every now and again I try to get serious about learning Clojure and every time I quit due to its documentation. I find it confusing. Nothing seems to be where it should be, there are almost no examples etc. So, every time I end up writing (in Java, I might add) a documentation browser with index, full-text search support, bookmarks (something similar to Eclipses help system or kchmviewer) and maybe a possibility of adding custom examples to meta :doc with aspiration of building a personal tutorial as I go along. I can't seem to find a way of obtaining that information from Clojures runtime in a standard manner, however. I tried tackling the 'problem' with evaluating a (map meta (reduce concat (map vals (map ns- publics (all-ns) and then parsing the result using Clojures java classes. I can do that without major problems. But I'm tired of doing it every time when some (sub)results type gets changed (the last one was from LazyCons to LazySeq) and I naively update everything from the SVN. Is there any guarantee with regard to the internal structure of evaluation results (speaking in Java terms)? If not, is there something planed to that effect for official release(s)? Alternatively, what's the best (quickest, most robust, ...) way of obtaining Clojures runtime info in a manner similar to this: MapString, interns // keys == distinct namespace names interns: MapString, meta // keys == distinct intern or public names meta: MapString, String (or MapString, ListString for the sake of arguments ;-) ) // keys == meta names in a sentence: something that could be parsed from within Java using java.lang.String and Java collection classes? Regards, David --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: [PATCH] Getting substrings counting from the end
Michael Wood esiot...@gmail.com writes: Makes sense to me, but there's a bug in your function. You want ( % 0) instead of ( 0 %). Quite right; good catch. thanks, 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 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: letfn - mutually recursive local functions
On Mar 1, 2009, at 4:18 PM, Konrad Hinsen wrote: On 01.03.2009, at 01:38, Rich Hickey wrote: I've added letfn, which lets you define mutually recursive local functions a la CL's labels. (defn ring [n] (letfn [(a [n] (if (zero? n) n (b (dec n (b [n] (if (zero? n) n (c (dec n (c [n] (if (zero? n) n (a (dec n] (c n))) I noticed that letfn does not permit destructuring in its argument lists: (letfn [(a [[f r]] f)] (a [1 2 3])) java.lang.IllegalArgumentException: fn params must be Symbols (NO_SOURCE_FILE:2) Is this intentional? Fixed in svn 1317 - thanks for the report. Rich --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure + Terracotta = Yeah, Baby!
Are any of the folks on this thread in/around the bay area? (I know Nabib is). We're having a clojure user-group meeting on the 12th of March - and the clojure/terracotta topic is of interest to a lot of people... It would be wonderful if someone would come and talk about the progress... Regards, Amit. http://www.meetup.com/The-Bay-Area-Clojure-User-Group/ On Mar 1, 8:37 am, Luc Prefontaine lprefonta...@softaddicts.ca wrote: We will go for a TIM. Just looked at the doc and tes that would simplify our work a lot. Thank you, Luc On Sat, 2009-02-28 at 18:48 -0800, Nabib El-Rahman wrote: Hi guys, I work for Terracotta ( on the server side ) and find this work with Clojure + Terracotta very exciting. Writing a TIM is definitely the way to go, It's a place to hide the glue until both Terracotta and Clojure catches up with each other. If you have any questions feel free to post on our forums http://forums.terracotta.org/forums/forums/list.page If you check out our trunk version, theres also an effort to make a common-api which will help writing a TIM easier for you guys. Good luck! -Nabib On Sat, Feb 28, 2009 at 12:02 PM, Luc Prefontane lprefonta...@softaddicts.ca wrote: We think the same way. Our first implementation of an alternative to AtomicReference is straightforward, we will look at improving it if the need arises. It will be easier to do so when we get stats from Terracotta after running some benchmarks. There's much to do before getting there. Luc On Sat, 2009-02-28 at 14:33 -0500, Paul Stadig wrote: In the Namespace case, it might be premature optimization to worry about AtomicReference being replaced. If there is a way to rewrite that code with, say, synchronized blocks, and it will work better with Terracotta, I think it would be worth doing. I don't think it would be normal usage to be updating the mappings and aliases in a namespace 1,000 times a second. AtomicReference is also used in Atom and Agent. Those cases may not be as straight forward. Paul On Sat, Feb 28, 2009 at 11:51 AM, Luc Prefontaine lprefonta...@softaddicts.ca wrote: 1) AtomicReference is used in several places. Instead of changing it, we think we can keep it when Clojure runs locally and provide an alternative when running in shared mode. AtomicReference is optimized to be efficient in a standalone JVM. We would like to keep it that way. Eventually Terracotta will provide instrumentation on this class by default so the shared implementation could be thrown away in the near future. We see the double implementations as a transition period until Terracotta supports it directly. 2) Noted Shared versus local mode: That's what we have in mind, getting Clojure to work in a shared mode versus a local/standalone mode. We want 0 impacts on the user code. Eventually we could use meta data to provide some hints that would allow us to fine tune shared interactions from user code. This would not impact local mode behaviours. We're not there yet but we know that this possibility exists so that's reassuring for the future. Integration is pretty simple once the common code base integrates the necessary changes. We need a shell script, a Terracotta configuration that will be maintained as part of the Clojure code base and some documentation. As of now we use a system property to toggle the modes, we will implement a transparent way (testing the presence of a terracotta property most probably). Luc -- Luc Préfontaine Off.:(514) 993-0320 Fax.:(514) 993-0325 Armageddon was yesterday, today we have a real problem... -- Luc Préfontaine Off.:(514) 993-0320 Fax.:(514) 993-0325 Armageddon was yesterday, today we have a real problem... --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: IntelliJ Clojure Plugin - Minor Indentation Issues.
Patrick, Please, create a ticket in our bugtracker for this issue: http://jetbrains.net/jira/browse/CLJ With best regards, Ilya Sergey On Mar 1, 7:22 pm, CuppoJava patrickli_2...@hotmail.com wrote: After using La Clojure a bit more, I noticed a few minor issues with the indentation system. Inside a let form binding, the next line should be indented to one character past the opening bracket. eg. should be like: (let [i hi j hi]) where j lines up with i. current behavior: (let [i hi j hi]) where j lines up with [ Also Nested forms, IMO, should be indented to be two spaces past the last opening parenthesis. eg. should be like: (let [i (fn [a] (println a))] current behavior: (let [i (fn [a] (fn [a] (println a)))] Those are the only two issues I've noticed so far. Everything else is working perfectly. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: IntelliJ Clojure Plugin - Minor Indentation Issues.
Patrick, Please, create a ticket in our bugtracker for this issue: http://jetbrains.net/jira/browse/CLJ With best regards, Ilya Sergey On Mar 1, 7:22 pm, CuppoJava patrickli_2...@hotmail.com wrote: After using La Clojure a bit more, I noticed a few minor issues with the indentation system. Inside a let form binding, the next line should be indented to one character past the opening bracket. eg. should be like: (let [i hi j hi]) where j lines up with i. current behavior: (let [i hi j hi]) where j lines up with [ Also Nested forms, IMO, should be indented to be two spaces past the last opening parenthesis. eg. should be like: (let [i (fn [a] (println a))] current behavior: (let [i (fn [a] (fn [a] (println a)))] Those are the only two issues I've noticed so far. Everything else is working perfectly. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Clojure + Terracotta = Yeah, Baby!
I'm in Montreal Quebec, we have several feet of snow here and still have a month of snow storms to go. Having some spare time I would love to visit you but there's too much work here and you area is a bit too far away :))) Luc On Sun, 2009-03-01 at 12:21 -0800, Amit Rathore wrote: Are any of the folks on this thread in/around the bay area? (I know Nabib is). We're having a clojure user-group meeting on the 12th of March - and the clojure/terracotta topic is of interest to a lot of people... It would be wonderful if someone would come and talk about the progress... Regards, Amit. http://www.meetup.com/The-Bay-Area-Clojure-User-Group/ On Mar 1, 8:37 am, Luc Prefontaine lprefonta...@softaddicts.ca wrote: We will go for a TIM. Just looked at the doc and tes that would simplify our work a lot. Thank you, Luc On Sat, 2009-02-28 at 18:48 -0800, Nabib El-Rahman wrote: Hi guys, I work for Terracotta ( on the server side ) and find this work with Clojure + Terracotta very exciting. Writing a TIM is definitely the way to go, It's a place to hide the glue until both Terracotta and Clojure catches up with each other. If you have any questions feel free to post on our forums http://forums.terracotta.org/forums/forums/list.page If you check out our trunk version, theres also an effort to make a common-api which will help writing a TIM easier for you guys. Good luck! -Nabib On Sat, Feb 28, 2009 at 12:02 PM, Luc Prefontane lprefonta...@softaddicts.ca wrote: We think the same way. Our first implementation of an alternative to AtomicReference is straightforward, we will look at improving it if the need arises. It will be easier to do so when we get stats from Terracotta after running some benchmarks. There's much to do before getting there. Luc On Sat, 2009-02-28 at 14:33 -0500, Paul Stadig wrote: In the Namespace case, it might be premature optimization to worry about AtomicReference being replaced. If there is a way to rewrite that code with, say, synchronized blocks, and it will work better with Terracotta, I think it would be worth doing. I don't think it would be normal usage to be updating the mappings and aliases in a namespace 1,000 times a second. AtomicReference is also used in Atom and Agent. Those cases may not be as straight forward. Paul On Sat, Feb 28, 2009 at 11:51 AM, Luc Prefontaine lprefonta...@softaddicts.ca wrote: 1) AtomicReference is used in several places. Instead of changing it, we think we can keep it when Clojure runs locally and provide an alternative when running in shared mode. AtomicReference is optimized to be efficient in a standalone JVM. We would like to keep it that way. Eventually Terracotta will provide instrumentation on this class by default so the shared implementation could be thrown away in the near future. We see the double implementations as a transition period until Terracotta supports it directly. 2) Noted Shared versus local mode: That's what we have in mind, getting Clojure to work in a shared mode versus a local/standalone mode. We want 0 impacts on the user code. Eventually we could use meta data to provide some hints that would allow us to fine tune shared interactions from user code. This would not impact local mode behaviours. We're not there yet but we know that this possibility exists so that's reassuring for the future. Integration is pretty simple once the common code base integrates the necessary changes. We need a shell script, a Terracotta configuration that will be maintained as part of the Clojure code base and some documentation. As of now we use a system property to toggle the modes, we will implement a transparent way (testing the presence of a terracotta property most probably). Luc -- Luc Préfontaine Off.:(514) 993-0320 Fax.:(514) 993-0325 Armageddon was yesterday, today we have a real problem... -- Luc Préfontaine Off.:(514) 993-0320 Fax.:(514) 993-0325 Armageddon was yesterday, today we have a real problem... -- Luc Préfontaine Off.:(514) 993-0320 Fax.:(514) 993-0325 Armageddon was yesterday, today we have a
Clojure desktop wallpaper request/discussion
I've been wishing I had one for a while now, to replace my Haskell wallpaper ;). Me and blbrown were talking in #Clojure and he suggested I make this post requesting that if anyone here has skill in image editing they could make a Clojure wallpaper. He said he wouldn't mind having one himself. My guess would be to enlarge the Clojure icon and go from there. I really don't care how it looks, I just suck at image editing and would love to have a Clojure wallpaper. Anyone got any ideas? -Rayne --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: IntelliJ Clojure Plugin - Minor Indentation Issues.
Ticket submitted. Thanks a lot -Patrick --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Algebraic data types in clojure.contrib
On Feb 26, 4:06 pm, Konrad Hinsen konrad.hin...@laposte.net wrote: On 26.02.2009, at 10:00, Konrad Hinsen wrote: I know, but as I said, my current implementation is just a proof of concept. It is not viable for production use for a variety of reasons. I was planning to replace it by something based on gen-class and proxy, but I will first try to get away with the new type function. I just committed a completely new implementation to clojure.contrib. It uses a vector with type metadata for representingalgebraicdata types. Overall I am rather happy with this version. It is used almost exactly like the previous one. There is probably still room for improvement, but I don't expect the interface to change significantly any more, so I'd say it's safe for adoption by adventurous Clojurians :-) I was wondering if you considered using maps or struct-maps for this. One of my pet peeves with algebraic data types is the unnamed, positional nature of the components/fields. It always bothers me you have to rename the fields in every pattern match, skip fields with _ etc. Rich --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: IntelliJ Clojure Plugin - Minor Indentation Issues.
I'm not an Intellij user, but: On Mar 2, 2:22 am, CuppoJava patrickli_2...@hotmail.com wrote: After using La Clojure a bit more, I noticed a few minor issues with the indentation system. Inside a let form binding, the next line should be indented to one character past the opening bracket. eg. should be like: (let [i hi j hi]) where j lines up with i. Agree on this. Also Nested forms, IMO, should be indented to be two spaces past the last opening parenthesis. eg. should be like: (let [i (fn [a] (println a))] That's three spaces... I'd say use the common indentation rules, which I thought was on space past the last opening parenthesis. But I just looked at one of the source files, and it's not consistent. When a pretty-printer is in place, I guess that could become the definition of the indentation rules. -- -asbjxrn --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Making agents able to temporarily yield place on thread pool
Not sure if I understand what you need, but could you build on the existing capability to send to the current agent: (send *agent* ...) ? You could have the agent send to itself, then exit the function with some work left to do that would be restarted on the next go-around. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Making agents able to temporarily yield place on thread pool
A non-important follow up question too: When I initially implemented without a type-hint for 'pool', it didn't work at all (deref would always be nil). I'm just curious why. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Concatenating many lists (stack overflow problem)
My ultimate goal is to get a list of all the words in a file in order. I have a function that will get a list of all the words on one line of this file in order, and I want to efficiently concatenate these lists to end up with one large list. I'm working with about 12000 lines right now, but in a perfect world I'd like to scale much higher. I started off just using concat. Basically my code looks like: (defn getstrlist ([file] (loop [x (getline file) worklst '()] (if x (recur (getline file) (concat worklst (splitstr x))) worklst Then in the REPL, if I type (def a (getstrlist FILE)), it works fine. But if I try to output a or take (first a), I get a stack overflow error. I don't know why this is. I remember hearing somewhere that Clojure had lazy sequences, so my best guess is that it isn't actually concatenating anything, but is storing pointers to the start of all the lists on a stack that overflows when I try to evaluate one of these pointers. I know in Scheme I would write this using metalists that keep track of the location of their last element: (define (concat metalst1 metalst2) (set-cdr! (car metalst1) (cdr metalst2)) (set-car! metalst1 (car metalst2)) metalst1) (define (make-metalst lst) (cons (get-end lst) lst)) (define (get-end lst) (if (null? lst) '() (if (null? (cdr lst)) lst (get-end (cdr lst) Which would be fairly efficient. But since Clojure doesn't seem to have real lists, I'm not quite sure how I could port this over. I suppose I could implement my own cons pairs like an idiot and do all of this manually, but I figure I'm just not understanding the Clojure solution to this problem. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Concatenating many lists (stack overflow problem)
Hi, The problem is that you end up with the front of your worklist being wrapped in n-lines nested calls to lazy-seq, one per each call to concat. Then, realizing the first element causes a stack overflow. This wouldn't happen if you reversed the arguments to concat, but then you wouldn't get what you want. Some possibilities (untested): ; probably the shortest, most idiomatic solution? (defn getstrlist [file] (apply concat (take-while identity (repeatedly #(getline file) ;or, using vectors, and written more like your solution: (defn getstrlist [file] (loop [worklst []] (if-let [x (getline file)] (recur (into worklst x)) worklst))) Cheers, Jason On Mar 1, 4:53 pm, Zededarian zededar...@gmail.com wrote: My ultimate goal is to get a list of all the words in a file in order. I have a function that will get a list of all the words on one line of this file in order, and I want to efficiently concatenate these lists to end up with one large list. I'm working with about 12000 lines right now, but in a perfect world I'd like to scale much higher. I started off just using concat. Basically my code looks like: (defn getstrlist ([file] (loop [x (getline file) worklst '()] (if x (recur (getline file) (concat worklst (splitstr x))) worklst Then in the REPL, if I type (def a (getstrlist FILE)), it works fine. But if I try to output a or take (first a), I get a stack overflow error. I don't know why this is. I remember hearing somewhere that Clojure had lazy sequences, so my best guess is that it isn't actually concatenating anything, but is storing pointers to the start of all the lists on a stack that overflows when I try to evaluate one of these pointers. I know in Scheme I would write this using metalists that keep track of the location of their last element: (define (concat metalst1 metalst2) (set-cdr! (car metalst1) (cdr metalst2)) (set-car! metalst1 (car metalst2)) metalst1) (define (make-metalst lst) (cons (get-end lst) lst)) (define (get-end lst) (if (null? lst) '() (if (null? (cdr lst)) lst (get-end (cdr lst) Which would be fairly efficient. But since Clojure doesn't seem to have real lists, I'm not quite sure how I could port this over. I suppose I could implement my own cons pairs like an idiot and do all of this manually, but I figure I'm just not understanding the Clojure solution to this problem. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: time complexity for immutable priority queue?
(for those browsing.. there is an immutable priority queue in constant time when favorable, but not unrealistic conditions) I woke up this morning dreaming about this queue and also recognized that count is linear. I have changed it to be constant. (defn priority-cons [priority data queue] (defstruct element :priority :data) (let [elem (struct element priority data) queue-first (if (nil? queue) nil (queue 'ffirst)) queue-rest (cond (nil? queue) nil (nil? elem) (queue 'rest) (= priority (queue-first :priority)) queue :else (priority-cons priority data (queue 'rest))) count (cond (nil? queue) 0 (nil? elem) (queue 'count) :else (inc (queue 'count)))] (fn [op] (cond (= op 'count) count (= op 'first) (cond (nil? queue) data (nil? elem) nil (= priority (queue-first :priority)) data :else (queue-first :data)) (= op 'ffirst) (cond (nil? queue) elem (nil? elem) nil (= priority (queue-first :priority)) elem :else queue-first) (= op 'rest) queue-rest I am beginning to wonder about insertion though. You say that insertion is linear and it recurses, but I'm seeing exponential time in practice. For instance, because the argument queue is a function that has been fully evaluated (meaning that calling any op on it is constant time), each of the function calls should be constant in helping to build the new function. The time to insert seems to be bogged down simply by the creation of the function which grows in size exponentially. Maybe I'm mistaken? (def rnd (java.util.Random.)) (time (loop [count 10] (if (= count 0) nil (do (.nextInt rnd 100) (priority-cons 10 hello nil) (recur (dec count)) (time (loop [queue nil count 3200] (if (= count 0) nil (do (recur (priority-cons (.nextInt rnd 100) hello queue) (dec count)) In playing with depth of the queue it is obvious that no one would ever use this. :) It appears that in practice the queue takes up exponentially amounts of memory. It seems to reach nearly 1GB with 3200 elements. I'm also guessing that the exponential amount of space is why for every doubling of length it takes roughly 4 times as long. This is definitely worse than linear. best run times for increasing length of x x time 25.786 502.2 100 6 200 27 400 101 800 571 1600 3426 3200 11842 And to be through I wrote an implementation that is similar to your answer. This one does not grow exponentially in space. It still suffers from terrible performance with any large number of entries. (defstruct element :priority :data) (defn priq-add [priority data queue] (let [elem (struct element priority data)] (loop [queue queue acc []] (cond (nil? queue) (conj acc elem) (= priority ((first queue) :priority)) (if (nil? acc) (cons elem queue) (concat acc (cons elem queue))) :else (recur (rest queue) (conj acc (first queue))) (def rnd (java.util.Random.)) (time (loop [queue nil count 12800] (if (= count 0) nil (do (let [nextInt (.nextInt rnd 100)] (recur (priq-add nextInt hello queue) (dec count))) And to be really through, I finally found a solution that is basically linear in insertion and removal assuming the span of priorities is around n/100 and evenly dispersed. (defn priq-add [priority data queue] (let [priority (* -1 priority) [cnt queue] queue] (if (nil? queue) (list 1 (sorted-map priority (list data))) (let [pri-list (queue priority) new-pri-list (if (nil? pri-list) (list data) (lazy-cons data pri-list))] (list (inc cnt) (assoc queue priority new-pri-list)) ; returns list of (data, new-queue) (defn priq-remove [queue] (if (nil? queue) nil (let [[cnt queue] queue key (first (keys queue)) value (queue key) data (first value) new-queue (if (= (count value) 1) (dissoc queue key) (assoc queue key (rest value))) ] (if (= cnt 1) (list data nil) (list data (list (dec cnt) new-queue)) (defn priq-count [queue] (if (nil? queue) 0 (first queue))) (def rnd (java.util.Random.)) (def big-q (time
Laziness madness
Hi, I find the laziness in clojure very hard to wrap my head around. I understand the idea and it's probably nice in theory. However, in real life it doesn't seem really useful beyond hardcore mathematical problems. Case in point, I just spent 2 hours debugging a piece of code (shown below) that seemed simple enough. This is the 3rd time this week that I've lost substantial time to laziness. I'm pretty pissed to tell the truth and I find myself wrapping things in doseq more and more just to be sure. I rarely use 'for' anymore, what's the point? Here is the code that gave me trouble: (map #(add-watch % watcher callback-fn) all-agents) This was not executing. I had to change it to the below expression: (doseq [agent all-labor-agents] (add-watch agent total-labor-agent callback-fn)) This second expression seems less elegant than the map above. Why doesn't clojure realize that an add-watch really should actually loop over all-agents? Why is it that Java calls are not made in similar expressions? Is laziness so useful that we should waste time investigating and fixing errors like this? Sure, there could be special constructs for laziness when we really need it. However, clojure shouldn't default to it IMO. At this point, laziness is a nice concept but it feels somewhat removed from reality to tell the truth. Of course I want to iterate over my collection when I'm doing an add-watch! What am I missing? Thanks, Max --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Laziness madness
doseq is the idiomatic way to write imperative code segments like this (add-watch generates a side-effect). Nevertheless, I too love using map for stuff like that. All you need to do is surround the map with dorun (or doall if you need the return value) and it will force the computation. see: (doc dorun) and (doc doall) On Mar 2, 7:06 am, max3000 maxime.lar...@gmail.com wrote: Hi, I find the laziness in clojure very hard to wrap my head around. I understand the idea and it's probably nice in theory. However, in real life it doesn't seem really useful beyond hardcore mathematical problems. Case in point, I just spent 2 hours debugging a piece of code (shown below) that seemed simple enough. This is the 3rd time this week that I've lost substantial time to laziness. I'm pretty pissed to tell the truth and I find myself wrapping things in doseq more and more just to be sure. I rarely use 'for' anymore, what's the point? Here is the code that gave me trouble: (map #(add-watch % watcher callback-fn) all-agents) This was not executing. I had to change it to the below expression: (doseq [agent all-labor-agents] (add-watch agent total-labor-agent callback-fn)) This second expression seems less elegant than the map above. Why doesn't clojure realize that an add-watch really should actually loop over all-agents? Why is it that Java calls are not made in similar expressions? Is laziness so useful that we should waste time investigating and fixing errors like this? Sure, there could be special constructs for laziness when we really need it. However, clojure shouldn't default to it IMO. At this point, laziness is a nice concept but it feels somewhat removed from reality to tell the truth. Of course I want to iterate over my collection when I'm doing an add-watch! What am I missing? Thanks, Max --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Concatenating many lists (stack overflow problem)
Thanks! One follow up question, though: will the first solution take O(n^2) time, or is clojure clever enough to keep track of where the end of a sequence is on its own (or, alternately, to start by concatenating the last two elements and working backward)? Or does it do some other cool magic to make this quick? On Mar 1, 9:07 pm, Jason Wolfe jawo...@berkeley.edu wrote: Hi, The problem is that you end up with the front of your worklist being wrapped in n-lines nested calls to lazy-seq, one per each call to concat. Then, realizing the first element causes a stack overflow. This wouldn't happen if you reversed the arguments to concat, but then you wouldn't get what you want. Some possibilities (untested): ; probably the shortest, most idiomatic solution? (defn getstrlist [file] (apply concat (take-while identity (repeatedly #(getline file) ;or, using vectors, and written more like your solution: (defn getstrlist [file] (loop [worklst []] (if-let [x (getline file)] (recur (into worklst x)) worklst))) Cheers, Jason On Mar 1, 4:53 pm, Zededarian zededar...@gmail.com wrote: My ultimate goal is to get a list of all the words in a file in order. I have a function that will get a list of all the words on one line of this file in order, and I want to efficiently concatenate these lists to end up with one large list. I'm working with about 12000 lines right now, but in a perfect world I'd like to scale much higher. I started off just using concat. Basically my code looks like: (defn getstrlist ([file] (loop [x (getline file) worklst '()] (if x (recur (getline file) (concat worklst (splitstr x))) worklst Then in the REPL, if I type (def a (getstrlist FILE)), it works fine. But if I try to output a or take (first a), I get a stack overflow error. I don't know why this is. I remember hearing somewhere that Clojure had lazy sequences, so my best guess is that it isn't actually concatenating anything, but is storing pointers to the start of all the lists on a stack that overflows when I try to evaluate one of these pointers. I know in Scheme I would write this using metalists that keep track of the location of their last element: (define (concat metalst1 metalst2) (set-cdr! (car metalst1) (cdr metalst2)) (set-car! metalst1 (car metalst2)) metalst1) (define (make-metalst lst) (cons (get-end lst) lst)) (define (get-end lst) (if (null? lst) '() (if (null? (cdr lst)) lst (get-end (cdr lst) Which would be fairly efficient. But since Clojure doesn't seem to have real lists, I'm not quite sure how I could port this over. I suppose I could implement my own cons pairs like an idiot and do all of this manually, but I figure I'm just not understanding the Clojure solution to this problem. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Laziness madness
Remember that you can force lazy sequences if you need to as you are with doseq with doall (retains head) and dorun (does not) as well. You probably want (dorun (map #(add-watch % watcher callback-fn) all-agents)) I think it's pretty clear here what's going on. Your code needs side-effects. In Clojure side-effect code tends to stands out. I sympathize with your frustration, I remember getting excited about Lisp macros but spending many many long hours trying to understand how to write even a simple one. Similarly I think lazy sequences are worth the initial frustration ;) On Mon, Mar 2, 2009 at 12:06 AM, max3000 maxime.lar...@gmail.com wrote: Hi, I find the laziness in clojure very hard to wrap my head around. I understand the idea and it's probably nice in theory. However, in real life it doesn't seem really useful beyond hardcore mathematical problems. Case in point, I just spent 2 hours debugging a piece of code (shown below) that seemed simple enough. This is the 3rd time this week that I've lost substantial time to laziness. I'm pretty pissed to tell the truth and I find myself wrapping things in doseq more and more just to be sure. I rarely use 'for' anymore, what's the point? Here is the code that gave me trouble: (map #(add-watch % watcher callback-fn) all-agents) This was not executing. I had to change it to the below expression: (doseq [agent all-labor-agents] (add-watch agent total-labor-agent callback-fn)) This second expression seems less elegant than the map above. Why doesn't clojure realize that an add-watch really should actually loop over all-agents? Why is it that Java calls are not made in similar expressions? Is laziness so useful that we should waste time investigating and fixing errors like this? Sure, there could be special constructs for laziness when we really need it. However, clojure shouldn't default to it IMO. At this point, laziness is a nice concept but it feels somewhat removed from reality to tell the truth. Of course I want to iterate over my collection when I'm doing an add-watch! What am I missing? Thanks, Max --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Concatenating many lists (stack overflow problem)
No, it will be O(n), where the cool magic is in the use of lazy sequences. Here's a very simple way to write an O(n) lazy concat: user (defn my-concat [ seqs] (when-first [s seqs] (if (seq s) (lazy-seq (cons (first s) (apply my-concat (rest s) (rest seqs (recur (rest seqs) user (my-concat '(1 2 3) [4 5] '(6 7)) (1 2 3 4 5 6 7) This is not proper lazy programming style, but it should give you the basic idea. The actual definition of concat is significantly more complicated: user (source concat) (defn concat Returns a lazy seq representing the concatenation of the elements in the supplied colls. ([] (lazy-seq nil)) ([x] (lazy-seq x)) ([x y] (lazy-seq (let [s (seq x)] (if s (cons (first s) (concat (rest s) y)) y ([x y zs] (let [cat (fn cat [xys zs] (lazy-seq (let [xys (seq xys)] (if xys (cons (first xys) (cat (rest xys) zs)) (when zs (cat (first zs) (next zs)))] (cat (concat x y) zs -Jason On Mar 1, 2009, at 9:47 PM, Zededarian wrote: Thanks! One follow up question, though: will the first solution take O(n^2) time, or is clojure clever enough to keep track of where the end of a sequence is on its own (or, alternately, to start by concatenating the last two elements and working backward)? Or does it do some other cool magic to make this quick? On Mar 1, 9:07 pm, Jason Wolfe jawo...@berkeley.edu wrote: Hi, The problem is that you end up with the front of your worklist being wrapped in n-lines nested calls to lazy-seq, one per each call to concat. Then, realizing the first element causes a stack overflow. This wouldn't happen if you reversed the arguments to concat, but then you wouldn't get what you want. Some possibilities (untested): ; probably the shortest, most idiomatic solution? (defn getstrlist [file] (apply concat (take-while identity (repeatedly #(getline file) ;or, using vectors, and written more like your solution: (defn getstrlist [file] (loop [worklst []] (if-let [x (getline file)] (recur (into worklst x)) worklst))) Cheers, Jason On Mar 1, 4:53 pm, Zededarian zededar...@gmail.com wrote: My ultimate goal is to get a list of all the words in a file in order. I have a function that will get a list of all the words on one line of this file in order, and I want to efficiently concatenate these lists to end up with one large list. I'm working with about 12000 lines right now, but in a perfect world I'd like to scale much higher. I started off just using concat. Basically my code looks like: (defn getstrlist ([file] (loop [x (getline file) worklst '()] (if x (recur (getline file) (concat worklst (splitstr x))) worklst Then in the REPL, if I type (def a (getstrlist FILE)), it works fine. But if I try to output a or take (first a), I get a stack overflow error. I don't know why this is. I remember hearing somewhere that Clojure had lazy sequences, so my best guess is that it isn't actually concatenating anything, but is storing pointers to the start of all the lists on a stack that overflows when I try to evaluate one of these pointers. I know in Scheme I would write this using metalists that keep track of the location of their last element: (define (concat metalst1 metalst2) (set-cdr! (car metalst1) (cdr metalst2)) (set-car! metalst1 (car metalst2)) metalst1) (define (make-metalst lst) (cons (get-end lst) lst)) (define (get-end lst) (if (null? lst) '() (if (null? (cdr lst)) lst (get-end (cdr lst) Which would be fairly efficient. But since Clojure doesn't seem to have real lists, I'm not quite sure how I could port this over. I suppose I could implement my own cons pairs like an idiot and do all of this manually, but I figure I'm just not understanding the Clojure solution to this problem. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Laziness madness
Thanks for the pointers. I was indeed able to make it work with dorun. ;) Still, I'm not sure I understand what all the fuss is about regarding laziness. I'll take your word for it for now but I hope to grock it eventually. Thanks! Max On Mar 2, 12:30 am, David Nolen dnolen.li...@gmail.com wrote: Remember that you can force lazy sequences if you need to as you are with doseq with doall (retains head) and dorun (does not) as well. You probably want (dorun (map #(add-watch % watcher callback-fn) all-agents)) I think it's pretty clear here what's going on. Your code needs side-effects. In Clojure side-effect code tends to stands out. I sympathize with your frustration, I remember getting excited about Lisp macros but spending many many long hours trying to understand how to write even a simple one. Similarly I think lazy sequences are worth the initial frustration ;) On Mon, Mar 2, 2009 at 12:06 AM, max3000 maxime.lar...@gmail.com wrote: Hi, I find the laziness in clojure very hard to wrap my head around. I understand the idea and it's probably nice in theory. However, in real life it doesn't seem really useful beyond hardcore mathematical problems. Case in point, I just spent 2 hours debugging a piece of code (shown below) that seemed simple enough. This is the 3rd time this week that I've lost substantial time to laziness. I'm pretty pissed to tell the truth and I find myself wrapping things in doseq more and more just to be sure. I rarely use 'for' anymore, what's the point? Here is the code that gave me trouble: (map #(add-watch % watcher callback-fn) all-agents) This was not executing. I had to change it to the below expression: (doseq [agent all-labor-agents] (add-watch agent total-labor-agent callback-fn)) This second expression seems less elegant than the map above. Why doesn't clojure realize that an add-watch really should actually loop over all-agents? Why is it that Java calls are not made in similar expressions? Is laziness so useful that we should waste time investigating and fixing errors like this? Sure, there could be special constructs for laziness when we really need it. However, clojure shouldn't default to it IMO. At this point, laziness is a nice concept but it feels somewhat removed from reality to tell the truth. Of course I want to iterate over my collection when I'm doing an add-watch! What am I missing? Thanks, Max --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Laziness madness
Hello, The way I think about it is am I in a portion of code that does pure functional stuff, or am I doing side effects ? A pure functional stuff resembles a computation, but not the storage part, or the part that gets the stuff from the outside (that is, no input / output stuff). doing side effects is when your function not only responds to a call to it by reading its input data and computing a new one that it returns, but also when it reads the input data, does some stuff to change the world (by accessing functions that will permanently change the world), and also (maybe) return a value. In this case, generally, comes with the non pure stuff the need to control the flow of execution of your program. That is : function A must be called before function B, and the effects of A on the world must have been realized before function B can run. In your case, you're calling add-watch which is clearly (to me) a side-effect function because it adds watchers to a long list of watchees by modifying them in place (side-effect). Generally speaking, if this talk about side-effect free function is still a little bit unclear to you, here are some smells to guess if a given function is pure or not : - does the function return a value (different from nil) ? If no - probably a function with side effect .. or a function that really does nothing ! - does the function return newly computed values ? If no - probably a function with side effect .. or a function that really does nothing ! (please note that the inverse is not true : you can't say that a function is pure just because it returns a new computed value of something) I would like to add a third rule to this list, but currently you will not encounter it for a lot of cases, yet it is correct in a number of case and I think it applies correctly to those cases : - does the function implementation use calls to functions ending with a ! ( e.g. set!) : those functions are performing side effects by permanently changing the value of something in the world. HTH, -- Laurent 2009/3/2 max3000 maxime.lar...@gmail.com Hi, I find the laziness in clojure very hard to wrap my head around. I understand the idea and it's probably nice in theory. However, in real life it doesn't seem really useful beyond hardcore mathematical problems. Case in point, I just spent 2 hours debugging a piece of code (shown below) that seemed simple enough. This is the 3rd time this week that I've lost substantial time to laziness. I'm pretty pissed to tell the truth and I find myself wrapping things in doseq more and more just to be sure. I rarely use 'for' anymore, what's the point? Here is the code that gave me trouble: (map #(add-watch % watcher callback-fn) all-agents) This was not executing. I had to change it to the below expression: (doseq [agent all-labor-agents] (add-watch agent total-labor-agent callback-fn)) This second expression seems less elegant than the map above. Why doesn't clojure realize that an add-watch really should actually loop over all-agents? Why is it that Java calls are not made in similar expressions? Is laziness so useful that we should waste time investigating and fixing errors like this? Sure, there could be special constructs for laziness when we really need it. However, clojure shouldn't default to it IMO. At this point, laziness is a nice concept but it feels somewhat removed from reality to tell the truth. Of course I want to iterate over my collection when I'm doing an add-watch! What am I missing? Thanks, Max --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Laziness madness
Quite a frequent occurrence, welcome to the club! One simple check that the Clojure compiler could make is to produce a warning if any lazy result is discarded. I think that would catch 90% of the problems and give the user an immediate clue what to investigate. Well it sounds simple, but I have no idea where to start implementing it. To me the big win of laziness is dealing with large collections, which would otherwise break. Regards, Tim. On Mar 2, 4:06 pm, max3000 maxime.lar...@gmail.com wrote: Hi, I find the laziness in clojure very hard to wrap my head around. I understand the idea and it's probably nice in theory. However, in real life it doesn't seem really useful beyond hardcore mathematical problems. Case in point, I just spent 2 hours debugging a piece of code (shown below) that seemed simple enough. This is the 3rd time this week that I've lost substantial time to laziness. I'm pretty pissed to tell the truth and I find myself wrapping things in doseq more and more just to be sure. I rarely use 'for' anymore, what's the point? Here is the code that gave me trouble: (map #(add-watch % watcher callback-fn) all-agents) This was not executing. I had to change it to the below expression: (doseq [agent all-labor-agents] (add-watch agent total-labor-agent callback-fn)) This second expression seems less elegant than the map above. Why doesn't clojure realize that an add-watch really should actually loop over all-agents? Why is it that Java calls are not made in similar expressions? Is laziness so useful that we should waste time investigating and fixing errors like this? Sure, there could be special constructs for laziness when we really need it. However, clojure shouldn't default to it IMO. At this point, laziness is a nice concept but it feels somewhat removed from reality to tell the truth. Of course I want to iterate over my collection when I'm doing an add-watch! What am I missing? Thanks, Max --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Laziness madness
Laziness hit home for me in Clojure when I noticed that one of our Java library functions, looking for a Collection, had happily accepted a Clojure (map ...) object which was going to expand a small set of integers into much larger objects. Because Clojure deferred the work, they were only generated when they were actually needed, and saved memory the rest of the time. Thanks, Stu On Mon, Mar 2, 2009 at 1:17 AM, Laurent PETIT laurent.pe...@gmail.comwrote: Hello, The way I think about it is am I in a portion of code that does pure functional stuff, or am I doing side effects ? A pure functional stuff resembles a computation, but not the storage part, or the part that gets the stuff from the outside (that is, no input / output stuff). doing side effects is when your function not only responds to a call to it by reading its input data and computing a new one that it returns, but also when it reads the input data, does some stuff to change the world (by accessing functions that will permanently change the world), and also (maybe) return a value. In this case, generally, comes with the non pure stuff the need to control the flow of execution of your program. That is : function A must be called before function B, and the effects of A on the world must have been realized before function B can run. In your case, you're calling add-watch which is clearly (to me) a side-effect function because it adds watchers to a long list of watchees by modifying them in place (side-effect). Generally speaking, if this talk about side-effect free function is still a little bit unclear to you, here are some smells to guess if a given function is pure or not : - does the function return a value (different from nil) ? If no - probably a function with side effect .. or a function that really does nothing ! - does the function return newly computed values ? If no - probably a function with side effect .. or a function that really does nothing ! (please note that the inverse is not true : you can't say that a function is pure just because it returns a new computed value of something) I would like to add a third rule to this list, but currently you will not encounter it for a lot of cases, yet it is correct in a number of case and I think it applies correctly to those cases : - does the function implementation use calls to functions ending with a ! ( e.g. set!) : those functions are performing side effects by permanently changing the value of something in the world. HTH, -- Laurent 2009/3/2 max3000 maxime.lar...@gmail.com Hi, I find the laziness in clojure very hard to wrap my head around. I understand the idea and it's probably nice in theory. However, in real life it doesn't seem really useful beyond hardcore mathematical problems. Case in point, I just spent 2 hours debugging a piece of code (shown below) that seemed simple enough. This is the 3rd time this week that I've lost substantial time to laziness. I'm pretty pissed to tell the truth and I find myself wrapping things in doseq more and more just to be sure. I rarely use 'for' anymore, what's the point? Here is the code that gave me trouble: (map #(add-watch % watcher callback-fn) all-agents) This was not executing. I had to change it to the below expression: (doseq [agent all-labor-agents] (add-watch agent total-labor-agent callback-fn)) This second expression seems less elegant than the map above. Why doesn't clojure realize that an add-watch really should actually loop over all-agents? Why is it that Java calls are not made in similar expressions? Is laziness so useful that we should waste time investigating and fixing errors like this? Sure, there could be special constructs for laziness when we really need it. However, clojure shouldn't default to it IMO. At this point, laziness is a nice concept but it feels somewhat removed from reality to tell the truth. Of course I want to iterate over my collection when I'm doing an add-watch! What am I missing? Thanks, Max --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---