Re: what does -> mean?
Hi Timothy, This is not really related to the current thread (sorry), but I want to say thanks for this API examples page, it looks like it'll be a great help, just what I need! Somehow I'd managed to completely miss it until now when you mentioned it - either I'm partially blind, or it could be better advertised? Cheers, Craig On Tue, Dec 30, 2008 at 4:25 AM, Timothy Pratley wrote: > > On Dec 30, 2:49 pm, wubbie wrote: >> Very criptic for newbie. >> What does "Threads the expr through the forms." mean? > > Shameless plug, if you find learning from examples easier than textual > descriptions, you might want to look up > http://en.wikibooks.org/wiki/Clojure_Programming/Examples/API_Examples > I'm trying to fully cover the entire API with snippets and examples as > I come across them... its pretty well fleshed out now, but still some > gaps to fill > > In this case the entry is: > > -> > > user=> (-> "hello" .toUpperCase (.replace "H" "J")) > "JELLO" > > However -> works on everything > user=> (-> true (if inc dec) (map [1 2 3])) > (2 3 4) > > or expanded > (map (if true inc dec) [1 2 3]) > > So one can also use macros and normal functions in ->, ie. non- > methods. > > > In this case -> is pretty difficult to get your head around in either > example or textual though, so YMMV :) > > > --~--~-~--~~~---~--~~ 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 code readable
Mark Volkmann a écrit : > For example, here's some code that I don't > know how to rewrite in a way that I find self-explanatory: > > (every? > #(<= (- (apple %) +grid-size+) (head %) (+ (apple %) +grid-size+)) > [+x-index+ +y-index+])) > > And here's another one: > > (assoc snake :body > (cons > (vec (map #(+ (dir %) ((first body) %)) [+x-index+ +y-index+])) > (if grow body (butlast body) > > Perhaps using your suggestion to go back and use a map with :x and :y > keys instead of a two-element vector to represent x/y coordinates > would help a little, but I'm still not sure the code would be > immediately obvious. > I think it would be clearer if we get rid of indexing: (every? #(<= (- *grid-size*) % *grid-size*) (map - apple head))) and (assoc snake :body (cons (map + dir (first body)) (if grow body (butlast body) and (defn paint [graphics [x y] color] (.setColor graphics color) (.fillRect graphics x y *grid-size* *grid-size*)) As a bonus, it works with any number of dimensions :-) Christophe --~--~-~--~~~---~--~~ 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: load-file within a do
Ah of course. Thanks a lot, your explanation makes things a lot clearer! I guess because of the direct nature of the REPL I hadn't thought about compile time vs runtime, but that makes perfect sense. On Dec 29, 8:00 pm, Meikel Brandmeyer wrote: > Hi Kees-Jochem, > > Am 29.12.2008 um 20:37 schrieb Kees-Jochem Wehrmeijer: > > > I created a small file foo.clj with the following contents: > > (defn foo [] :bar) > > > Then from a REPL I try the following: > > (do (load-file "foo.clj") (foo)) > > > but this gives an error message: > > java.lang.Exception: Unable to resolve symbol: foo in this context > > (NO_SOURCE_FILE :1) > > You have to distinguish compile time from runtime. > The load-file happens during runtime. However the > compiler looks about foo already during compile > time. But since the file is not loaded, the compiler > doesn't find foo and, hence, complains. > > > Strangely enough, the following does work: > > (do (load-file "foo.clj") (ns-interns 'user)) > > This returns {foo #'user/foo} (as expected) > > Not at all strange: Since the *call* to ns-interns > happens at runtime, the foo.clj is already loaded. > Hence, foo is defined and everything is fine. > > > So, while it seems that the file gets loaded and > > the function gets added to the namespace, calling > > it from within the do doesn't seem to work. What's > > going on? > > So it's not actually the do, but the different times > when things happen. > > Instead of load-file, use a namespace. Although, > this may already be a bit involved depending how far > you already got with your learning. > > Create a file named foo/bar.clj in your classpath. > In this file put the following: > > (ns foo.bar) > > (defn foo [] :bar) > > Then do at the Repl: > > (use 'foo.bar) > (foo) > > This should work without problems, since use loads > the file at compile time. So the compiler knows > about the foo definition and everything works out. > > Hope this helps. > > Sincerely > Meikel > > smime.p7s > 5KViewDownload --~--~-~--~~~---~--~~ 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: Understanding how to use namespaces
Hi, using namespaces also requires to layout the files in a certain way. For the following consider the directory cp to be in the classpath. Create a file cp/permutations.clj with your functions: (ns permutations) (defn fun1 ...) (defn fun2 ...) Then create your second namespace in the corresponding file. Note that I introduced a dot to get directories into discussion, because dots in namespaces translate to directories in filenames. So put the test code into the file cp/test/perms.clj. (ns test.perms (:require permutations)) (defn some-test [] (permutations/fun1)) Require should be preferred over use, since it doesn't pollute the namespace. And you see where all the functions come from. For a function which is used only once or twice this is certainly sufficient. If you need the functions more often and your prefix is too long, you can easily assign an alias. (ns test.perms (:require [some.long.prefix.permutations :as p])) (defn some-test [] (p/fun1)) If you want to use use, you should consider using the :only option. This imports only the functions named. For example, when we use only the function fun1, then there is no reason to also suck in fun2 just polluting our namespace. Another advantage: we see (as with require) where the function comes from. (ns test.perms (:use [permutations :only (fun1)])) (defn some-test [] (fun1)) Then you can use test.perms similarly from other files or from the Repl in the same way discussed above. (ns testperms (:use permutations)) This doesn't work at all, so I must have the syntax wrong. No, the syntax is correct. Since you didn't provide the error ("It doesn't work!" is not the error), I can only guess. But my suspicion is that clojure told you something like the following: 1:3 user=> (ns testperms (:use permutations)) java.io.FileNotFoundException: Could not locate permutations__init.class or permutations.clj on classpath: (repl-1:3) It is important to remember: - The files must be in the classpath! - The namespace a.b.c has to be defined in the file a/b/c.clj. This is a VVFAQ. It was explained on the list by Chouser, me and others in every detail several times during the last days alone, not to mention the months before. Stressing the Google "Find" button and reading the failure message are not a bad things. Sincerely Meikel smime.p7s Description: S/MIME cryptographic signature
Re: In core structure editor, anyone?
On Tue, Dec 30, 2008 at 1:24 AM, falcon wrote: > > How's textjure coming along? Not ready yet. :-/ Current sub-project: setting up sufficiently flexible system to handle vi-style keybindings. --Chouser --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: How to encapsulate local state in closures
On Dec 29, 8:08 pm, "Mark Engelberg" wrote: > On Mon, Dec 29, 2008 at 12:40 PM, Rich Hickey wrote: > > People who know what they are doing can do these things right now with > > Clojure's array support. There really isn't any more value for Clojure > > to add to that, so no special primitives. I fully accept the necessity > > of doing that at times, and the correctness of internally mutating, > > but externally referentially transparent functions, and Clojure has > > several of them. That's one of the reasons Clojure isn't 'pure'. OTOH > > it's not a good argument for mutable local vars. What other "unsafe > > things" are you looking for? > > After giving this some more thought, I think the absolutely simplest > way to further improve Clojure's mutability support would be to add an > atom-set function for the cases where you really want to clobber the > contents of atom and don't care what the contents already are. This > takes the "variable which needs no synchronization" thing one step > further, allowing for fastest speed in those situations. > > The semantics would be like this: > (defn atom-set [a val] > (swap! a (constantly val))) > > But presumably it could be implemented in the Clojure core in a way > that is even faster than the above implementation, since it doesn't > need to do the check that the contents haven't changed before setting. > I think this is consistent with the idea of atom as a power-user's > tool for getting the best possible performance when synchronization is > not required. Could you provide an example of when you would need/use that? 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: Parallel words frequency ranking
On Dec 29, 7:02 am, Chouser wrote: > > (defn split-string-in-two [s] > > (let [chunk-size (quot (count s) 2)] > > [(subs s 0 chunk-size), (subs s chunk-size)])) > > Might this cut a word in half and produce (slightly) incorrect > results? True, I decided to let it be for the sake of simplicity. > > 1. Is there a better way to do it? Perhaps agents should share some > > data structure? > > I've got lots to learn in the realm of parallel program design, but > the sequential summing step at the end stood out to me. Perhaps > another agent that just does incremental summing along the way would > reduce the running time. > > Also, the entire file is read in by a single thread -- perhaps the use > of mmap would allow the agents to start counting sooner and reduce > total run time that way. You may want to look at clojure.contrib.mmap Thanks for suggestion. In fact, mmap/slurp is *much* faster than built-in slurp. Now, my program starts with: (ns com.wlodarek.examples (:require [clojure.contrib.mmap]) (:require [clojure.contrib.duck-streams])) (defn read-file [filepath] (str (clojure.contrib.mmap/slurp filepath))) (defn write-file [filepath string] (clojure.contrib.duck-streams/spit filepath string)) ; ... I hope Clojure will soon have fast, reasonably named read/write file functions built in the core. Now I'm trying to parallelize also the formatting part, and to move from 2 agents to n agents. Again, thanks for all tips! regards, Piotrek --~--~-~--~~~---~--~~ 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 code readable
On Tue, Dec 30, 2008 at 4:21 AM, Christophe Grand wrote: > > Mark Volkmann a écrit : >> For example, here's some code that I don't >> know how to rewrite in a way that I find self-explanatory: >> >> (every? >> #(<= (- (apple %) +grid-size+) (head %) (+ (apple %) +grid-size+)) >> [+x-index+ +y-index+])) >> >> And here's another one: >> >> (assoc snake :body >> (cons >> (vec (map #(+ (dir %) ((first body) %)) [+x-index+ +y-index+])) >> (if grow body (butlast body) >> >> Perhaps using your suggestion to go back and use a map with :x and :y >> keys instead of a two-element vector to represent x/y coordinates >> would help a little, but I'm still not sure the code would be >> immediately obvious. >> > I think it would be clearer if we get rid of indexing: > > (every? #(<= (- *grid-size*) % *grid-size*) > (map - apple head))) > > and > > (assoc snake :body >(cons > (map + dir (first body)) The previous line needs to be (vec (map + dir (first body))). > (if grow body (butlast body) > > and > > (defn paint [graphics [x y] color] > (.setColor graphics color) > (.fillRect graphics x y *grid-size* *grid-size*)) Excellent improvements! Thank you very much! I've updated http://www.ociweb.com/mark/programming/ClojureSnake.html to include these changes. > As a bonus, it works with any number of dimensions :-) Except for the fact that Java's Graphics object doesn't know how to paint in 3D. ;-) -- 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: making code readable
Mark Volkmann a écrit : >> (assoc snake :body >>(cons >> (map + dir (first body)) >> > > The previous line needs to be (vec (map + dir (first body))). > It works without the vec. Since we aren't using indexing anymore we don't need to make a vector: a seq (or any collection type) is enough. > Except for the fact that Java's Graphics object doesn't know how to > paint in 3D. ;-) Indeed. It works with n dimensions but you only see a 2D projection of the play area :-( Christophe --~--~-~--~~~---~--~~ 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: Contrib REPL Invocation Changes
On Monday 29 December 2008 20:50, Stephen C. Gilardi wrote: > > ... > > Here it is working with the current clojure.jar and > clojure-contrib.jar: > > % java -cp clojure.jar:clojure-contrib.jar clojure.contrib.repl_ln > Clojure > 1:1 user=> (prn "hi") > "hi" > nil > 1:2 user=> I can't replicate that: % java -cp /repo/JT/clojure-svn/clojure/clojure.jar:/repo/JT/clojure-svn/clojure-contrib/clojure-contrib.jar clojure.contrib.repl_ln Exception in thread "main" java.lang.NoClassDefFoundError: clojure/contrib/repl_ln Caused by: java.lang.ClassNotFoundException: clojure.contrib.repl_ln at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) Could not find the main class: clojure.contrib.repl_ln. Program will exit. Please accept that all the path names are correct, I checked carefully and more than once and both Clojure Core and Contrib are up-to-date with the current SVN (as of this writing, of course). Anyway, I guess it needs to be pointed that the invocation you supplied won't work unless the Clojure Contrib JAR file is built with pre- compiled Java classes and that this only happens if you supply the clojure.jar property ("-Dclojure.jar=path/to/clojure.jar") to your Ant invocation when you build Clojure Contrib. Once I figured that out, the problem went away. Is this documented anywhere? > ... > > --Steve Randall Schulz --~--~-~--~~~---~--~~ 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: Stumped - Java hangs when using Swing in Slime
Wow... that actually fixes it. Still a minor problem, since according to the Sun website, it is legal to create a Swing object in another thread as long as long as it is not "realized" yet... Still, this definitely is a doable workaround. Thanks! -Luke On Dec 29, 9:17 pm, Rowdy Rednose wrote: > What if you run the Swing code in the Event Dispatch Thread? > > In other words, does this: > > (. javax.swing.SwingUtilities (invokeAndWait #(. > javax.swing.JOptionPane (showMessageDialog nil "Hello World" > > or > > (. javax.swing.SwingUtilities (invokeLater #(. javax.swing.JOptionPane > (showMessageDialog nil "Hello World" > > work for you? > > On 20 Dez., 06:06, Daniel Eklund wrote: > > > > Anyone have any ideas? I'm pretty confused as to what might be going > > > on. Some sort of deadlock in the thread pool that isn't allowing the > > > AWT event thread any cycles? I'm looking at the thread pool in JSwat > > > and I see a lot of Swank threads, but I can't tell exactly what's > > > going on. > > > I literally just had this problem today. I was having slime hang on > > me with _any_ swing code. So I tried the basic repl and even the most > > basic > > > (. javax.swing.JOptionPane (showMessageDialog nil "Hello World")) > > > and even this was failing. Spent an hour svn updating, etc. > > > Finally, I clicked on the system icon tray at the bottom right of XP > > and noticed that that the stupid Java download manager wanted me to > > update. I let it download whatever patch it wanted and then suddenly > > everything worked. > > > It could be coincidental. But I am telling you just in case. --~--~-~--~~~---~--~~ 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 code readable
On Mon, Dec 29, 2008 at 4:10 PM, Chouser wrote: > I believe the idiom for global values like this is to place asterisks > around the name. I thought the asterisk convention was for variables intended for dynamic binding. It took me a minute to figure out where I got that idea. "Programming Clojure" suggests it (without quite saying it) in chapter 6, section 3. "Vars intended for dynamic binding are sometimes called special vari- ables. It is good style to name them with leading and trailing asterisks." Obviously the book's a work in progress, but that does sound reasonable. A special convention for variables whose values change (or that my code's welcome to rebind) seems more useful to me than one for "globals" (though I'm not sure I'd consider something like grid-size for a given application a global). Based on ants.clj it appears Rich doesn't feel there needs to be a special naming convention for that sort of value. What's your read on that, Chouser? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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: Understanding how to use namespaces
Hey Mark, In addition to Meikel's explanation above, have a look at this message http://groups.google.com/group/clojure/msg/17ada41fcb5ef667 from the overall thread http://groups.google.com/group/clojure/browse_frm/thread/ff80d120c996ba1a/9bfbfe1b08246035# This was the post that finally made it clear (for me) the differences between use, require, refer, load etc Namespaces and library loading are intertwined. daniel --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: test-is nesting
On Mon, Dec 29, 2008 at 9:12 PM, Larrytheliquid wrote: > > This is what I'm thinking, let me explain: http://gist.github.com/41468 > (If you are familiar with RSpec, here is the equivalent RSpec example > http://rspec.info/examples.html) I really like the look of this so far. Nice work! > Another change is that the "test" macro can take a symbol, a string, or both > as arguments. This allows for more specification/RSpec/BDD-like tests to be > created (I noticed you're experimenting with something similar in > clojure-contrib tests, in the form of test-that). This is exactly the reason that I threw the test-that in there. I was finding it difficult to adequately document the intent of some of the tests I was writing without resorting to extensive comments. The test-that macro, though it doesn't do much now, was intended to be the start of some RSpec-inspired features, but I hadn't put much thought into it yet and it's a good thing because I like where you are going much more. Regards, - J. --~--~-~--~~~---~--~~ 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: Some code review for clj-record?
I see what you are doing with the validations and defining them in the init-modelcall. I think that's a good idea actually and like it better than my solution to putting the callbacks in the model namespace. A couple of small things that I noticed when starting to play around with clj-record. In your example you have: (ns com.example.user) (clj-record.core/init-model) but when I do that I get the error: java.lang.ClassNotFoundException: clj-record.core When I add a require it clears it up like: (ns com.example.user (:require [clj-record.core :as cr.core])) (cr.core/init-model) I know this is picky, but in your clj-record.core/init-model function you have: (first (reverse (re-split #"\." (name (ns-name *ns*) and could be changed to: (last (re-split #"\." (name (ns-name *ns* I look forward to seeing clj-record progress. Thanks John. On Mon, Dec 29, 2008 at 10:20 PM, John D. Hume wrote: > > On Mon, Dec 29, 2008 at 7:15 PM, Brian Doyle > wrote: > > I noticed that in the init-model macro you are creating a 'defn table [] > > ...' function in the > > model namespace and was wondering why you didn't just make it a def > instead, > > since > > it doesn't take any args? > > That didn't occur to me. I do like the idea of all the functionality > being available directly on clj-record.core with model name as a first > argument in addition to being defined in the model namespace, so I > guess that's one reason. But the inference of table name from model > name should only be the default, so maybe it would be better to just > def it there and let clj-record.core look it up there if needed, > somewhat as you recommended doing for callbacks... > > > I have an idea for you with the callbacks like, before-create, > after-create, > > etc. In the > > all-models-metadata in the core.clj you could store the namespace in the > > hash > > associated with the model-name on setup. Then in the create function > > defined in > > the core.clj you could call the before-create function defined in the > model > > something > > like: > > > > (let-if [bc ('before-create (ns-publics )] (bc > > attributes#)) > > That's interesting. It's basically the opposite of the way I did the > validation stuff, where you pass in validation functions and those get > stored away in metadata and aren't directly accessible. (Here > "metadata" is not used in the clojure.org/metadata sense of the word. > I've thought about using clojure metadata to store model info, but I > don't know what symbol or collection I'd attach it to.) I think I > prefer the validation approach, because those functions have a certain > job to do and shouldn't be sitting there cluttering the model > namespace. (On the other hand, it is awfully convenient to be able to > test those functions directly.) > > Thanks again for looking. If you or anyone else has further comments, > I'd like to hear them. > git clone git://github.com/duelinmarkers/clj-record.git > > -hume. > > -- > http://elhumidor.blogspot.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: Accessing "this" in gen-class constructor
Ah sorry I missed that. However, you accomplished this only because there exists a constructor in Thread that takes a String name argument. As a general case, it's not usually that convenient... ie. public class MyThread extends Thread{ public MyThread(){ setName("This is my thread"); setPropertyA("bla bla bla"); setPropertyB("bla bla bla"); etc... } } --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
swank-clojure license
Sorry for this e-mail that could be more targeted to Jeffrey Chu, but I was unable to find its direct e-mail address, and I know he is a clojure ml member, so ... It seems that swank-clojure license is a flavor of GPL ("License as distributed with Emacs"). So I guess that if for clojure-dev (eclipse plugin for clojure) we want to use it for interactivity with an external clojure environment, and we want to start the environment from the plugin, we have a problem : stop me if I'm wrong, but if any file of swank-clojure is embedded in clojure-dev plugin, then the license of clojure-dev must be GPL-compatible (and clojure-dev follows clojure convention and is currently EPL licensed). Jeffrey, could it be an option for you to dual license swank-clojure in both GPL and EPL ? What other options could I have ? (except the one of not using swank- clojure, of course :-) Thanks in advance, Regards, -- Laurent --~--~-~--~~~---~--~~ 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: Accessing "this" in gen-class constructor
On Tue, Dec 30, 2008 at 11:52 AM, CuppoJava wrote: > > Ah sorry I missed that. > > However, you accomplished this only because there exists a constructor > in Thread that takes a String name argument. > As a general case, it's not usually that convenient... > > ie. > > public class MyThread extends Thread{ > public MyThread(){ >setName("This is my thread"); >setPropertyA("bla bla bla"); >setPropertyB("bla bla bla"); >etc... > } > } Seems like that class has a rather unfortunate API. :-) As far as I know, this is not currently possible with gen-class. Seems like you'd need some kind of post-constructor hook, provided just to deal with mutable state of the base class. I wonder if Rich would accept a patch providing an :after-ctor option to gen-class. --Chouser --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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: Parallel words frequency ranking
In an ideal world, standard functions like map, sort, reduce, filter, etc. would know when to parallelize on their own, or even better, the compiler will do it for them. Meanwhile, I tried playing with the parallel lib ( http://clojure.org/other_libraries ) which has functions like preduce, psort, and par:map functions, but I wasn't very successful. Anyone who knows what s/he's doing can shed some light on how to use it with this example? Mibu P.S. psort and sort's arguments are inconsistent (psort [coll comp] vs. sort [comp coll]). On Dec 30, 3:56 pm, Piotr 'Qertoip' Włodarek wrote: > On Dec 29, 7:02 am, Chouser wrote: > > > > (defn split-string-in-two [s] > > > (let [chunk-size (quot (count s) 2)] > > > [(subs s 0 chunk-size), (subs s chunk-size)])) > > > Might this cut a word in half and produce (slightly) incorrect > > results? > > True, I decided to let it be for the sake of simplicity. > > > > 1. Is there a better way to do it? Perhaps agents should share some > > > data structure? > > > I've got lots to learn in the realm of parallel program design, but > > the sequential summing step at the end stood out to me. Perhaps > > another agent that just does incremental summing along the way would > > reduce the running time. > > > Also, the entire file is read in by a single thread -- perhaps the use > > of mmap would allow the agents to start counting sooner and reduce > > total run time that way. You may want to look at clojure.contrib.mmap > > Thanks for suggestion. > > In fact, mmap/slurp is *much* faster than built-in slurp. > > Now, my program starts with: > > (ns com.wlodarek.examples > (:require [clojure.contrib.mmap]) > (:require [clojure.contrib.duck-streams])) > > (defn read-file [filepath] > (str (clojure.contrib.mmap/slurp filepath))) > > (defn write-file [filepath string] > (clojure.contrib.duck-streams/spit filepath string)) > > ; ... > > I hope Clojure will soon have fast, reasonably named read/write file > functions built in the core. > > Now I'm trying to parallelize also the formatting part, and to move > from 2 agents to n agents. > > Again, thanks for all tips! > > regards, > Piotrek --~--~-~--~~~---~--~~ 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: swank-clojure license
lpetit writes: > So I guess that if for clojure-dev (eclipse plugin for clojure) we > want to use it for interactivity with an external clojure environment, > and we want to start the environment from the plugin, we have a > problem : stop me if I'm wrong, but if any file of swank-clojure is > embedded in clojure-dev plugin, then the license of clojure-dev must > be GPL-compatible (and clojure-dev follows clojure convention and is > currently EPL licensed). > > What other options could I have ? (except the one of not using swank- > clojure, of course :-) You could ask the Eclipse devs to dual-license. =) I'm not too well-versed in legal lore, but as I understand it, the compatibility issues come into play if you're creating a "derived work". It doesn't matter if GPL-licensed files are *distributed* with clojure-dev; it just matters if they are part of the same program. -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: swank-clojure license
I'm not sure. From what I remember, what you describe is more related to LGPL ? On 30 déc, 18:19, Phil Hagelberg wrote: > lpetit writes: > > So I guess that if for clojure-dev (eclipse plugin for clojure) we > > want to use it for interactivity with an external clojure environment, > > and we want to start the environment from the plugin, we have a > > problem : stop me if I'm wrong, but if any file of swank-clojure is > > embedded in clojure-dev plugin, then the license of clojure-dev must > > be GPL-compatible (and clojure-dev follows clojure convention and is > > currently EPL licensed). > > > What other options could I have ? (except the one of not using swank- > > clojure, of course :-) > > You could ask the Eclipse devs to dual-license. =) > > I'm not too well-versed in legal lore, but as I understand it, the > compatibility issues come into play if you're creating a "derived > work". It doesn't matter if GPL-licensed files are *distributed* with > clojure-dev; it just matters if they are part of the same program. > > -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: test-is nesting
If you guys can get these changes sorted out quickly (next few weeks) I would love to cover them in the book. No pressure. :-) Thanks, Stuart > On Mon, Dec 29, 2008 at 9:12 PM, Larrytheliquid > wrote: >> >> This is what I'm thinking, let me explain: http://gist.github.com/41468 >> (If you are familiar with RSpec, here is the equivalent RSpec example >> http://rspec.info/examples.html) > > I really like the look of this so far. Nice work! > >> Another change is that the "test" macro can take a symbol, a >> string, or both >> as arguments. This allows for more specification/RSpec/BDD-like >> tests to be >> created (I noticed you're experimenting with something similar in >> clojure-contrib tests, in the form of test-that). > > This is exactly the reason that I threw the test-that in there. I was > finding it difficult to adequately document the intent of some of the > tests I was writing without resorting to extensive comments. The > test-that macro, though it doesn't do much now, was intended to be the > start of some RSpec-inspired features, but I hadn't put much thought > into it yet and it's a good thing because I like where you are going > much more. > > Regards, > > - J. > > > --~--~-~--~~~---~--~~ 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: In core structure editor, anyone?
I would be super interested in trying things out with textjure whenever you are ready. I don't want to give up emacs + slime, but I do think it is an interesting concept to connect to a running process and change it. One other thing that LISP had that was useful was saving the state of the system. We can't really save the state of the jvm, but we could re-jar any files with changed code, or perhaps (maybe a better idea) create add-on jars that overrode old code with new code? Chris On Dec 30, 6:46 am, Chouser wrote: > On Tue, Dec 30, 2008 at 1:24 AM, falcon wrote: > > > How's textjure coming along? > > Not ready yet. :-/ Current sub-project: setting up sufficiently > flexible system to handle vi-style keybindings. > > --Chouser --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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 code readable
What about some sort of lint program? I'm thinking about something like pylint for clojure with configurable rules, but which will default to the standards agreed upon bu the clojure community. Even if you don't follow the rules 100%, it could be useful to see where you are deviating to be sure you really mean to in that situation. Plus it'd be a good coding exercise. -Mitch On Dec 30, 12:50 am, "Mark H." wrote: > On Dec 29, 1:15 pm, "Mark Volkmann" wrote: > > > It's early enough in the life of Clojure that we haven't developed any > > deeply held habits yet. I think it would be a good idea for you and > > other Clojure committers to at least suggest the way you think things > > should be done in code. If you think surrounding names of constants > > with plus signs is a good way to identify them as such, I'll gladly > > start doing that for the sake of consistency. I don't think it's a > > good idea for all of us to simply do what feels good because that will > > make it harder to read code written by others. > > Indeed, standards are good, but I do think part of the "Lisp way" (for > good or ill) is to treat such standards less like dogma and more like > gentle admonitions. > > There does seem to be a little of a "culture clash" latent in this > discussion, between those with the "Lisp ethos" and those with the > "Java ethos." It has very little to do with naming conventions for > variables, and very much to do with the level of playfulness and > academic interest one has when approaching a new programming > language: do I ask, "ooo, how many lines of code do I need in order > to express this infinite data structure?" or "how do I get my Web 2.0 > application up and running with the least effort?". Both of these are > good questions to ask: every serious computer science task needs both > application to motivate theory, and theory to improve existing > applications and inspire new ones. It's fun to see a language like > Clojure motivate both groups of people and get them talking -- Rich > has done great work in that respect by taking suggestions from both > groups and creating the space for them to interact. > > It might be fun to make a list of books that folks on one side could > read to get the sense of how the other side thinks. > > mfh --~--~-~--~~~---~--~~ 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: Contrib REPL Invocation Changes
On Dec 30, 2008, at 9:53 AM, Randall R Schulz wrote: Anyway, I guess it needs to be pointed that the invocation you supplied won't work unless the Clojure Contrib JAR file is built with pre- compiled Java classes and that this only happens if you supply the clojure.jar property ("-Dclojure.jar=path/to/clojure.jar") to your Ant invocation when you build Clojure Contrib. Once I figured that out, the problem went away. Is this documented anywhere? I'm not aware of it being documented anywhere. I've added clojure.contrib.repl-ln/stream-repl to support something like your original invocation: % java -cp clojure.jar:clojure-contrib.jar clojure.main -e "(use 'clojure.contrib.repl-ln) (stream-repl)" This works whether or not clojure-contrib.jar contains compiled code. --Steve smime.p7s Description: S/MIME cryptographic signature
Re: Accessing "this" in gen-class constructor
Haha yeah... it's a rather poor API. I'm making do with a temporary post-constructor hook that I manually call after instantiating the object right now. But it's tedious and error-prone. Thanks for the help Chouser --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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: swank-clojure license
lpetit writes: > I'm not sure. From what I remember, what you describe is more related > to LGPL ? No, the LGPL allows using the code in another program that is Free but not GPL-licensed. If you're just distributing some code from swank-clojure, licensing conflicts will never come into play. It's only about incorporating it into another codebase. -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 -~--~~~~--~~--~--~---
Accessing static protected fields?
Hi, Is there anyway to access a static protected field from within Clojure? I've tried using :exposes in gen-class, however that gives me the following error: java.lang.IncompatibleClassChangeError: Expected non-static field graphics.JMEGame.ALWAYS_SHOW_PROPS_DIALOG Thanks for your replies -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: Accessing static protected fields?
On Dec 30, 2008, at 1:27 PM, CuppoJava wrote: > > Hi, > Is there anyway to access a static protected field from within > Clojure? > > I've tried using :exposes in gen-class, however that gives me the > following error: > > java.lang.IncompatibleClassChangeError: Expected non-static field > graphics.JMEGame.ALWAYS_SHOW_PROPS_DIALOG > > Known problem: http://code.google.com/p/clojure/issues/detail?id=2 Patch welcome. 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: Accessing static protected fields?
Ah okay. I'll dig through the clojure source today and see if I'm able to make a patch myself. Thanks for the reply 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: test-is nesting
On Dec 29, 9:12 pm, Larrytheliquid wrote: > As I get closer to something I like, it seems that what I will end up with > will end up with will look look like where test-is seems to be heading. Hi Larry, You have laid out pretty clearly where I would like test-is to go next. I've been experimenting with a "context" macro and have thought about using strings for test names. I feel like there are two slightly different directions the library could go right now, so I need more feedback on what is most useful to people using it. So, here's a dump of what's in my brain right now, open for comment/discussion. Originally, I assumed tests would be defined in metadata, like this: (defn my-function ([x y] ... do stuff ...) {:test (fn [] (is (= 12 (my-function 3 4))) I felt it was beneficial to have tests and code right next to each other, and the clojure.core/test function suggested that this would be a good style for Clojure. But it seems like no one except me is using test-is that way. Instead, most people are using "deftest", which is fine, just not what I anticipated. In the current design of test-is, every test must be attached to the :test metadata of a Var. That's why "deftest" currently requires a symbol, even a generated one -- it needs a Var to attach the metadata to. The "run-tests" function iterates through every Var in a namespace, looks for a function in the :test metadata, and calls it. I like and use RSpec, but I felt it was better suited to the Object- Oriented style of Ruby than to the Lispy style of Clojure. But maybe not. Recently, I changed "deftest" so that tests can be called like normal functions, and nested, like this: (deftest foo ) (deftest bar ...) (deftest everything (foo) (bar)) This was inspired by Peter Seibel's example in Practical Common Lisp: http://www.gigamonkeys.com/book/practical-building-a-unit-test-framework.html This allows tests to be nested, but it still works within the tests- are-Var-metadata framework. Failure reports give the nested names, like "Failure in (everything foo)". Trying to add "contexts" confuses things a bit. What is a "context", exactly? In RSpec, it maps conceptually to a class, with external state handled by before/after functions. You can do that in test-is now: (deftest in-context-foo ... setup context ... ... call each test function ... ... teardown context ...) This way, you can re-use the same test function in multiple contexts. In RSpec, tests are defined in a single context, so it's a little less flexible (without the addition of share-test and use-test, as in Specjure). So, finally, here are the two directions I feel test-is could go next: 1. RSpec-style: Abandon the Var/metadata framework, use strings for test names, and store tests in a global data structure. 2. Keep tests as functions, add doc strings, use nested tests for context. I prefer 2, because I think it's more functional and requires less bookkeeping code. For example, in specjure, you added share-test, use- test, $assoc!, and $get. The first two are unnecessary if tests are functions, and the latter two can be handled by binding, like this: (declare *stack*) (deftest peek-returns-nil (is (nil? (peek *stack*))) (deftest with-empty-stack (binding [*stack* (list)] (peek-returns-nil Basically, I think tests are easier to write when they look more like ordinary code. You also get automatic bonuses, like source line numbers, from the compiler. One last thing: it seems to be often overlooked that the "is" macro can take a second argument, a doc string: (is (= 4 (+ 2 2)) "two and two make four") That doc string will be included in failure reports. If I add doc strings to deftest, you've basically got all the necessary infrastructure for RSpec-style comment strings. signing off, for now, -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 -~--~~~~--~~--~--~---
Re: Parallel words frequency ranking
On Dec 30, 9:18 am, Mibu wrote: > In an ideal world, standard functions like map, sort, reduce, filter, > etc. would know when to parallelize on their own, or even better, the > compiler will do it for them. The former is easier than the latter ;-) Even the smartest autoparallelizing compilers rely on manual annotations to expose lack of sequential dependencies in loops, but a function's API can guarantee that parallelism and let the function's implementation do the heavy lifting. It takes so much effort to write a "good" (read "aggressively optimizing") compiler that major releases come out on the same schedule as major CPU releases, which means users don't get time to work out all the bugs on the current (hardware,software) combination before the next compiler and CPU come out. Besides, compiler bugs are incredibly frustrating for users (trust me). This means it's better to have simpler compilers and smarter libraries. mfh --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
metaprogramming: finding function arity and other information about the envrionment
How do I find the arity of a given function? I can get a list of all name spaces using (all-ns) I can get functions within each name space using (find-ns 'clojure) ; so map find-ns over each value returned by all-ns (doc fn) gives me a description of the function, and information about function arity. I assumed the description and arity were part of metadata but (meta fn) only returns nil (for a few functions I tried). So what am I doing wrong? Generally speaking, how can I get information about my environment: -which bindings exist -the source code for a given function (if source code is available) -function arity -etc. Thanks --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Parallel words frequency ranking
On Dec 28, 7:50 pm, Piotr 'Qertoip' Włodarek wrote: > On 38MB file it takes 28s, compared to 38s of similar but sequential > version. Another good thing is to make a simple performance model, perhaps aided by timings of individual components, before you start parallelizing everything ;-) How long does it take just to read in the file (with or without mmap)? How long does it take one agent to finish its count? How long does the reduction over agents' counts at the end take? If you're concerned about the latter being a sequential sum, how does its performance vary as a function of the number of agents? The total performance of your implementation should be (time for slurp) + (time for one agent to count its words) + (time for reduction over agents), not counting the time to start up the agents. Unless you have a RAID array or a serious parallel filesystem, (time for slurp) is just a fixed overhead you have to eat. btw how many processors do you have? mfh --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
send-off *agent* #' func
Hi, Why do we need to specify the second argument(#'func) is a function, not a variable? the syntax of send-off required a function as the second arg? thanks, sun --~--~-~--~~~---~--~~ 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: metaprogramming: finding function arity and other information about the envrionment
On Dec 30, 10:29 pm, falcon wrote: > (doc fn) gives me a description of the function, and information about > function arity. I assumed the description and arity were part of > metadata but (meta fn) only returns nil (for a few functions I tried). Be sure to var-quote the function, i.e. don't use (meta print), but (meta #'print). For this example, this returns a dictionary containing an entry for the key :arglists, so you can get the argument lists specified for the function with (:arglists (meta #'whatever)). --~--~-~--~~~---~--~~ 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: metaprogramming: finding function arity and other information about the envrionment
Impressive, source file and line numbers are already included! I need to better understand reader macro (or where ever # comes from). Thanks > > Be sure to var-quote the function, i.e. don't use (meta print), but > (meta #'print). --~--~-~--~~~---~--~~ 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: metaprogramming: finding function arity and other information about the envrionment
On Dec 30, 11:08 pm, falcon wrote: > Impressive, source file and line numbers are already included! > I need to better understand reader macro (or where ever # comes from). You actually need to know two things regarding this issue. In function-definitions, the meta-data is actually assigned to the var referring to the function, not the function itself. For example, if you have a (defn some-fun [x] nil), this creates a var named some-fun that is assigned a function and its meta-data. Now, if you would use a plain (meta some-fun), you'd be referring to meta-data of the thing that the var some-fun is holding (the function itself, which has no meta-data assigned). The #' reader macro is the Clojure way of saying "I mean to the var itself, not the thing the var points to". I hope this explanation is not too confusing. --~--~-~--~~~---~--~~ 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: send-off *agent* #' func
On Tue, Dec 30, 2008 at 4:56 PM, wubbie wrote: > > Why do we need to specify the second argument(#'func) is a function, > not a variable? > the syntax of send-off required a function as the second arg? The second argument will be called as a function -- if it's not callable (doesn't implement IFn), you'll get an exception: user=> (send-off (agent nil) 42) java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn Perhaps you're asking why #'func is sometimes used instead of just func? This is probably because the code was written to work with older versions of Clojure. The difference is a bit subtle, but the overview is that the #' prefix used to be required if you wanted to be able to update the definition of 'func' and have the next send it made to itself use that new definition. This is no longer necessary, and you can now use simply: (send-off *agent* func) I don't understand all the details of what changed (or when), but here's what I do know. #'func evaluates to the Var named "func" (which in turn holds the current value, presumably a function). On the other hand just plain 'func' evaluates to the *current value* of the Var named func. To demonstrate the difference: user=> filter ; get the current value of filter # user=> (var filter) ; get the Var named "filter" -- can be written #'filter #'clojure.core/filter user=> (deref (var filter)) ; get the Var, and then the value -- can be written @#'filter # Note the return value of the first and last examples are the same, because they're doing essentially the same thing. But I said 'send-off' needs a function, so how can we use #'func which actually passes in a Var? That's because Vars implement IFn -- when called, they deref themselves and call their current value: user=> (instance? clojure.lang.IFn #'filter) true user=> (#'filter identity [1 nil 2]) (1 2) Presumably in some older version of Clojure, using the plain symbol 'func' caused the Var to be deref'ed only once, such that the initial value of the Var was used even when if you used 'def' or 'defn' to update the implementation for 'func'. I don't know when this initial deref happened -- I don't think it could have been at compile time, or there would have been no way to forward-declare and have mutually-dependant functions definitions. Perhaps it was the first time 'func' was called? Anyway, it's easy to demonstrate that the #'func format is no longer needed for self-sending agents: user=> (defn act [i] (Thread/sleep 1000) (prn i) (send-off *agent* act) (inc i)) #'user/act user=> (send-off (agent 100) act) # user=> 100 101 102 103 (defn act [i]) #'user/act user=> 104 After the manual 'send-off', a number was printed every second. Then I used 'defn' to update the Var named 'act' to be a function that does nothing all. Because 'act' was sitting in it's 'sleep' call, one more number was printed, but the next 'send-off' used the new definition of 'act' and nothing more was done. --Chouser --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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: metaprogramming: finding function arity and other information about the envrionment
On Tue, Dec 30, 2008 at 4:29 PM, falcon wrote: > > Generally speaking, how can I get information about my environment: > -which bindings exist > -the source code for a given function (if source code is available) pmf's explanations are solid, but for the source code in particular, you may be interested in clojure.contrib.repl-utils/source, which allows interaction like: user=> (source filter) (defn filter "Returns a lazy seq of the items in coll for which (pred item) returns true. pred must be free of side-effects." [pred coll] (when (seq coll) (if (pred (first coll)) (lazy-cons (first coll) (filter pred (rest coll))) (recur pred (rest coll) --Chouser --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com 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 -~--~~~~--~~--~--~---
REPL Subtleties. Emacs inferior-mode.
Hi, I'm just noticing some subtle threading problems when running a Jme application from the REPL within inferior-lisp mode Emacs. For instance this works: (. jmetest.renderer.TestArrow main nil) But this doesn't: (attempting to execute from a separate thread) (def thread (proxy [Thread] [] (run [] (. jmetest.renderer.TestArrow main nil (. thread start) The REPL just hangs. This only happens when using the REPL from within Emacs. Not when I run the REPL in windows command prompt. Any help at all would be greatly appreciated. -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: swank-clojure license
On Dec 30, 10:26 am, Phil Hagelberg wrote: > lpetit writes: > > I'm not sure. From what I remember, what you describe is more related > > to LGPL ? > > No, the LGPL allows using the code in another program that is Free but > not GPL-licensed. Actually the LGPL allows linking to the library (somewhat different than "using the code") from any program, even one which is not under an open-source license. "L" used to stand for "library" and the canonical example of a LGPL library is GNU's libc: any program can link to it, and such linkage doesn't make the program have the same license as libc. mfh --~--~-~--~~~---~--~~ 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: metaprogramming: finding function arity and other information about the envrionment
Makes sense, thanks On Dec 30, 5:29 pm, pmf wrote: > On Dec 30, 11:08 pm, falcon wrote: > > > Impressive, source file and line numbers are already included! > > I need to better understand reader macro (or where ever # comes from). > > You actually need to know two things regarding this issue. > > In function-definitions, the meta-data is actually assigned to the var > referring to the function, not the function itself. For example, if > you have a (defn some-fun [x] nil), this creates a var named some-fun > that is assigned a function and its meta-data. > > Now, if you would use a plain (meta some-fun), you'd be referring to > meta-data of the thing that the var some-fun is holding (the function > itself, which has no meta-data assigned). The #' reader macro is the > Clojure way of saying "I mean to the var itself, not the thing the var > points to". > > I hope this explanation is not too confusing. --~--~-~--~~~---~--~~ 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: metaprogramming: finding function arity and other information about the envrionment
I was thinking of writing a poor man's enclojure (to get a feel for a real clojure project). Looks like a lot of work is already done :) I see many references to clojure contrib, perhaps this jar could be made more prominent on clojure.org? On Dec 30, 5:40 pm, Chouser wrote: > On Tue, Dec 30, 2008 at 4:29 PM, falcon wrote: > > > Generally speaking, how can I get information about my environment: > > -which bindings exist > > -the source code for a given function (if source code is available) > > pmf's explanations are solid, but for the source code in particular, > you may be interested in clojure.contrib.repl-utils/source, which > allows interaction like: > > user=> (source filter) > (defn filter > "Returns a lazy seq of the items in coll for which > (pred item) returns true. pred must be free of side-effects." > [pred coll] > (when (seq coll) > (if (pred (first coll)) > (lazy-cons (first coll) (filter pred (rest coll))) > (recur pred (rest coll) > > --Chouser --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: test-is nesting
Thanks for the reply Stuart, I thought about similar things. I'm still not sure which approach is better myself, but let me clarify a few things. In the current design of test-is, every test must be attached to > the :test metadata of a Var. That's why "deftest" currently requires > a symbol, even a generated one -- it needs a Var to attach the > metadata to. The "run-tests" function iterates through every Var in a > namespace, looks for a function in the :test metadata, and calls it. > I like and use RSpec, but I felt it was better suited to the Object- > Oriented style of Ruby than to the Lispy style of Clojure. But maybe > not. The fact that this is approach is implemented with anamorphic forms instead of just function calls is something that has troubled me as well. However, right now I'm leaning towards it being the better decision because a common testing pattern is encapsulated with it, and the production namespaces remain clean (I'll explain what I mean below.) I definitely encourage using vanilla pure functions over side effects, but Clojure does have references types and I think the anamorphic approach lends itself to testing these more easily, while keeping the simple case of testing the pure functions easy (not using context, and only using test.) > Trying to add "contexts" confuses things a bit. What is a "context", > exactly? In RSpec, it maps conceptually to a class, with external > state handled by before/after functions. You can do that in test-is > now: > > (deftest in-context-foo > ... setup context ... > ... call each test function ... > ... teardown context ...) > > This way, you can re-use the same test function in multiple contexts. > In RSpec, tests are defined in a single context, so it's a little less > flexible (without the addition of share-test and use-test, as in > Specjure). One thing that should be clarified here is that share-test does create a test, but rather creates a shareable function that is named with a string instead of a symbol. That's all it is, you could just use functions if you wanted to. However, the reasoning behind using it is to avoid creating functions in your production namespace. As test-is is currently implemented, when you deftest you create vars in the namespace you are in. Although these are gensym'd, it seems like a smell to me to be creating clojure vars in your produciton namespace (ie: what if production code happened to do something with all tests in namespaces and inadvertently gathered the test functions?) Now, I admit that this may be a rare occurrence, but when testing software I prefer to keep the test and production environments as close as possible to avoid potentially hard to track down production bugs (in this case where your test tells you one thing because of those extra functions existing during test time, but they don't exist in production.) One thing you can do to make this less of a problem is create specific test-namespaces for your tests. But, here you lose the ability to test private functions, and production functions may still be trying to do something with all namespaces (rather than just their own namespace.) How I implemented "context/test" and "share-test" may clarify this: share-test is just a reference to struct that contains contains a :name string key, and a :fn function key. The *shared-tests* symbol is kept in the specjure namespace, and when you use-test it does a (get *shared-tests* :name "my shared test name") and calls the functions with any extra arguments passed to use-test. The other reference in the specjure namespace is *tests* which contains an array of context structs. This struct has the context doc string, an array of before functions, an array of after functions, and an array of test functions (there is also one context with nil as its doc string that is used for test functions defined without being in a context.) Whenver you run a test, each test function is iterated through. Each iteration binds the *parameters* var to an empty map for use with $get/$assoc!, calls the before functions in order, then calls the function, and finally calls the after functions in order. Another advantage of having these 2 pieces of data be separate from production namespaces is test cleanup. If you develop in a repl, you often reload files and run your tests as you make changes to your files and tests. To avoid keeping around tests that you've deleted, you can simply ref-set *tests* and *shared-tests* to a fresh array and map, respectively. In test-is right now, you have the arguably more complex task of going through all symbols in all namespaces, and clearing their test metadata. > > > So, finally, here are the two directions I feel test-is could go next: > 1. RSpec-style: Abandon the Var/metadata framework, use strings for > test names, and store tests in a global data structure. > 2. Keep tests as functions, add doc strings, use nested tests for > context. > > I prefer 2, because I think it's
Re: How to encapsulate local state in closures
On Tue, Dec 30, 2008 at 5:53 AM, Rich Hickey wrote: > Could you provide an example of when you would need/use that? > Sure. Use Case #1: Implementing classic imperative algorithms Consider the binary gcd algorithm on page 338 of The Art of Computer Programmiing, volume 2. This is a very clever implementation of gcd using only bit shifting and parity checking. Like many classic algorithms, it is written in a very imperative style. The following is a direct translation to Clojure: (defn binary-gcd [a b] (let [k (atom 0), u (atom a), v (atom b), t (atom 0), algsteps {:B1 (fn [] (if (and (even? @u) (even? @v)) (do (atom-set k (inc @k)) (atom-set u (bit-shift-right @u 1)) (atom-set v (bit-shift-right @v 1)) :B1) :B2)), :B2 (fn [] (if (odd? @u) (do (atom-set t (- @v)) :B4) (do (atom-set t @u) :B3))), :B3 (fn [] (atom-set t (bit-shift-right @t 1)) :B4), :B4 (fn [] (if (even? @t) :B3 :B5)) :B5 (fn [] (if (> @t 0) (atom-set u @t) (atom-set v (- @t))) :B6), :B6 (fn [] (atom-set t (- @u @v)) (if (not (zero? @t)) :B3 (bit-shift-left @u @k)))}] (loop [step :B1] (let [next ((algsteps step))] (if (number? next) next (recur next)) To test this code, I used the following implementation of atom-set: (defn atom-set [a val] (swap! a (constantly val))) Now, the code would certainly be cleaner if Clojure had tail-call optimization and letrec, because you could set each algorithmic step up as a mutually recursive function, rather than storing the steps in a hash table, and setting up a driver loop to handle the state changes as in a state machine. Or if Clojure just had letrec, this could be expressed using the new trampoline construct. But that's not really the point. The point here is that this code took me no effort to translate from the Knuth book, it worked on the first run with no debugging needed, and anyone can easily compare this code against the Knuth pseudocode, and see at a glance that this is a correct implementation of that algorithm. There may be ways to convert this to a functional style (and I encourage others to try it as an interesting exercise), but with any such transformation, it will be significantly more difficult to confirm that the program correctly implements the algorithm. About half of the atom-sets are updates that could use the swap! function, but many of these are replacing the atom's contents with something completely unrelated to its existing contents. Use Case #2: setting up mutually referential data structures A common way to set up mutually referential data structures is to start them off with links that are set to nil, and then use imperative setting to direct the links at the right things. As a quick example, consider the cyclic-linked-list solution to the classic Josephus problem. Here is one way to set up a cyclic ring of people: (defn make-person [n] {:id n, :link (atom nil)}) (defn link-people [p1 p2] (atom-set (p1 :link) p2)) (defn ring-people [n] (let [vec-people (vec (map make-person (range n)))] (dotimes [i (dec n)] (link-people (vec-people i) (vec-people (inc i (link-people (vec-people (dec n)) (vec-people 0)) (vec-people 0))) Now depending on how this is going to be used, you could argue that maybe you're better served by refs. But if the whole point of atoms is to give power-users another, faster choice when no coordination is needed, why not give the programmer a choice here? If I know for sure that I'm just going to use this ring within a single thread, or use it internally in a function that generates and uses the ring without ever exposing the ring outside that function, then an atom may be the right tool for the job. --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~--- binarygcd.clj Description: Binary data josephus.clj Description: Binary data
Re: REPL Subtleties. Emacs inferior-mode.
On Dec 30, 2008, at 5:53 PM, CuppoJava wrote: > > Hi, > I'm just noticing some subtle threading problems when running a Jme > application from the REPL within inferior-lisp mode Emacs. > > For instance this works: > > (. jmetest.renderer.TestArrow main nil) > > But this doesn't: (attempting to execute from a separate thread) > > (def thread (proxy [Thread] [] > (run [] > (. jmetest.renderer.TestArrow main nil > (. thread start) > > The REPL just hangs. I don't know why proxying Thread isn't working, but I do this to start up jME from the REPL in a separate thread: (.start (Thread. (fn [] (.start viewport Where viewport is an instance of a subclass of BaseSimpleGame that was created via gen-class. That's on Mac OS X with Java 1.6. That's using revision 1150 of Clojure and swank-clojure from around the same time (Dec 10). > > > This only happens when using the REPL from within Emacs. Not when I > run the REPL in windows command prompt. > > Any help at all would be greatly appreciated. > -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: Stumped - Java hangs when using Swing in Slime
Just curious - do both invokeLater and invokeAndWait work? Or only invokeLater? On 31 Dez., 00:39, levand wrote: > Wow... that actually fixes it. Still a minor problem, since according > to the Sun website, it is legal to create a Swing object in another > thread as long as long as it is not "realized" yet... > > Still, this definitely is a doable workaround. Thanks! > > -Luke > > On Dec 29, 9:17 pm, Rowdy Rednose wrote: > > > What if you run the Swing code in the Event Dispatch Thread? > > > In other words, does this: > > > (. javax.swing.SwingUtilities (invokeAndWait #(. > > javax.swing.JOptionPane (showMessageDialog nil "Hello World" > > > or > > > (. javax.swing.SwingUtilities (invokeLater #(. javax.swing.JOptionPane > > (showMessageDialog nil "Hello World" > > > work for you? > > > On 20 Dez., 06:06, Daniel Eklund wrote: > > > > > Anyone have any ideas? I'm pretty confused as to what might be going > > > > on. Some sort of deadlock in the thread pool that isn't allowing the > > > > AWT event thread any cycles? I'm looking at the thread pool in JSwat > > > > and I see a lot of Swank threads, but I can't tell exactly what's > > > > going on. > > > > I literally just had this problem today. I was having slime hang on > > > me with _any_ swing code. So I tried the basic repl and even the most > > > basic > > > > (. javax.swing.JOptionPane (showMessageDialog nil "Hello World")) > > > > and even this was failing. Spent an hour svn updating, etc. > > > > Finally, I clicked on the system icon tray at the bottom right of XP > > > and noticed that that the stupid Java download manager wanted me to > > > update. I let it download whatever patch it wanted and then suddenly > > > everything worked. > > > > It could be coincidental. But I am telling you just in case. --~--~-~--~~~---~--~~ 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: Stumped - Java hangs when using Swing in Slime
Luke, I believe they don't promote the "as long as it's not yet realized" rule anymore but rather say "do even creation of Swing objects in the EDT" now: http://java.sun.com:80/docs/books/tutorial/uiswing/concurrency/initial.html Cheers Rowdy On 31 Dez., 00:39, levand wrote: > Wow... that actually fixes it. Still a minor problem, since according > to the Sun website, it is legal to create a Swing object in another > thread as long as long as it is not "realized" yet... > > Still, this definitely is a doable workaround. Thanks! > > -Luke > > On Dec 29, 9:17 pm, Rowdy Rednose wrote: > > > What if you run the Swing code in the Event Dispatch Thread? > > > In other words, does this: > > > (. javax.swing.SwingUtilities (invokeAndWait #(. > > javax.swing.JOptionPane (showMessageDialog nil "Hello World" > > > or > > > (. javax.swing.SwingUtilities (invokeLater #(. javax.swing.JOptionPane > > (showMessageDialog nil "Hello World" > > > work for you? > > > On 20 Dez., 06:06, Daniel Eklund wrote: > > > > > Anyone have any ideas? I'm pretty confused as to what might be going > > > > on. Some sort of deadlock in the thread pool that isn't allowing the > > > > AWT event thread any cycles? I'm looking at the thread pool in JSwat > > > > and I see a lot of Swank threads, but I can't tell exactly what's > > > > going on. > > > > I literally just had this problem today. I was having slime hang on > > > me with _any_ swing code. So I tried the basic repl and even the most > > > basic > > > > (. javax.swing.JOptionPane (showMessageDialog nil "Hello World")) > > > > and even this was failing. Spent an hour svn updating, etc. > > > > Finally, I clicked on the system icon tray at the bottom right of XP > > > and noticed that that the stupid Java download manager wanted me to > > > update. I let it download whatever patch it wanted and then suddenly > > > everything worked. > > > > It could be coincidental. But I am telling you just in case. --~--~-~--~~~---~--~~ 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: REPL Subtleties. Emacs inferior-mode.
Thanks Matt, I was actually hoping for you to reply. I found one of your earlier posts mentioning that you got JME working properly interactively with the REPL. Unfortunately, your solution didn't seem to work. I seem to be having the same problem as the guy in this post: http://groups.google.com/group/clojure/browse_thread/thread/6c195c35ae9a7eb8 By the way, what is the difference between (. mythread start) and (.start mythread)? --~--~-~--~~~---~--~~ 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: REPL Subtleties. Emacs inferior-mode.
On Dec 30, 2008, at 9:13 PM, CuppoJava wrote: > > Thanks Matt, > I was actually hoping for you to reply. I found one of your earlier > posts mentioning that you got JME working properly interactively with > the REPL. > > Unfortunately, your solution didn't seem to work. I seem to be having > the same problem as the guy in this post: > http://groups.google.com/group/clojure/browse_thread/thread/6c195c35ae9a7eb8 Hrmm, sorry I can't help you there. Could upgrade your OS. *ducks* ;-) > > > By the way, what is the difference between (. mythread start) and > (.start mythread)? The latter is a macro that expands to the former: user> (macroexpand '(.start thread)) (. thread start) > > > --~--~-~--~~~---~--~~ 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: REPL Subtleties. Emacs inferior-mode.
Haha, I'm now seriously considering getting a Mac... Anyway thanks for your help. I think I'll try installing Slime and Swank and see if that helps at all. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: test-is nesting
Hi Larry, hi all, Just a quick note: this is not a complete answer, but I just added the "testing" macro, which lets you add nested documentation strings to tests, as in RSpec. I've also removed the "T-..." gensyms for now; every deftest must have a symbol name. user> (use 'clojure.contrib.test-is) nil user> (deftest my-tests (testing "Arithmetic" (testing "with integers" (testing "should work" (is (= 5 (+ 2 2))) #'user/my-tests user> (run-tests) Testing user FAIL in (my-tests) (NO_SOURCE_FILE:1) Arithmetic with integers should work expected: (= 5 (+ 2 2)) actual: (not= 5 4) Ran 1 tests containing 1 assertions. 1 failures, 0 errors. nil user> -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 -~--~~~~--~~--~--~---
Re: Stumped - Java hangs when using Swing in Slime
I want to add that it's not confined to just Swing applications. I have the exact same problem using JME on an Emacs *inferior-lisp* REPL. The program hangs, until I enter subsequent commands on the REPL. The SwingUtilities trick, and updating to the latest Java runtime doesn't help. I'm going to try installing latest Slime/Swank to see if that helps at all. If anyone's worked out the root cause of this problem, please post it here. -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: How to encapsulate local state in closures
Timothy Pratley wrote: >> I think if Clojure could do something like this (enforce a certain >> kind of referentially transparent mutable local), that would be neat, >> > > It is possible to achieve this behavior explicitly: > (defn create-add-2 [] > (with-local-vars [x 1] > (do > (var-set x 2) > (let [z @x] > (fn [y] (+ y z)) > (def myc (create-add-2)) > user=> (myc 1) > 3 > user=> (myc 2) > 4 > > A bit verbose, but also very clear about what is really mutable and > what isn't. > > > I am trying to understand the arguments here... so here is a summary. Please let me know if I missed something: 1) It is possible to get "internally" mutable state using with-local-vars and var-set. The problem here is that the "internal" state cannot be operated on my multiple threads concurrently. Thus functions defined this way will not automatically scale on multi-cores. One may have to be careful while wrapping such state in a closure and accessing it from multiple threads. However, they *will* allow to "naturally" write certain algorithms containing local mutation. 2) It is possible to get "internally" mutable state using clojure arrays and recur style re-binding. The problem here is that recur style rebinding may not be expressive enough to "naturally" encode certain algorithms. 3) It is possible to get "internally" mutable state using atoms (along with atom-set for better readability and convenience)... which seems like a nice suggestion. The problem here is the generic problem with atoms which should be used carefully under do-sync. Particularly, if an atom is indeed an "internal" state in a function's closure, and the closure itself is used in a transaction then we have problems due to transaction retries. So, we either use atoms assuming that the function closures *will* be retried in transactions which limits the situations in which atoms can be used or we make sure we document such function closures so that they are not used in do-sync (may be clojure can print a warning if it sees an atom being used inside a do-sync). However, this problem occurs only if there is a closure. If the function is retried and the internal state is created afresh then do we still have a problem? Is this a valid way to handle "internal" mutable state which is not encapsulated in closures? So can we conclude that atoms with atom-set can be freely used in functions which don't return closures around them and if we really need to do that, we should use refs instead (or use one of the first two options given in the beginning)? Pinocchio --~--~-~--~~~---~--~~ 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: How to encapsulate local state in closures
On Dec 30, 2008, at 6:29 PM, Mark Engelberg wrote: > On Tue, Dec 30, 2008 at 5:53 AM, Rich Hickey > wrote: >> Could you provide an example of when you would need/use that? >> > > Sure. > > Use Case #1: Implementing classic imperative algorithms > > Consider the binary gcd algorithm on page 338 of The Art of Computer > Programmiing, volume 2. This is a very clever implementation of gcd > using only bit shifting and parity checking. Like many classic > algorithms, it is written in a very imperative style. The following > is a direct translation to Clojure: > > (defn binary-gcd [a b] > (let [k (atom 0), u (atom a), v (atom b), t (atom 0), > algsteps {:B1 (fn [] (if (and (even? @u) (even? @v)) > (do (atom-set k (inc @k)) > (atom-set u (bit-shift-right @u 1)) > (atom-set v (bit-shift-right @v 1)) > :B1) > :B2)), > :B2 (fn [] (if (odd? @u) > (do (atom-set t (- @v)) :B4) > (do (atom-set t @u) :B3))), > :B3 (fn [] (atom-set t (bit-shift-right @t 1)) :B4), > :B4 (fn [] (if (even? @t) :B3 :B5)) > :B5 (fn [] (if (> @t 0) > (atom-set u @t) > (atom-set v (- @t))) > :B6), > :B6 (fn [] (atom-set t (- @u @v)) > (if (not (zero? @t)) :B3 (bit-shift-left @u @k)))}] >(loop [step :B1] > (let [next ((algsteps step))] > (if (number? next) next (recur next)) > > To test this code, I used the following implementation of atom-set: > (defn atom-set [a val] > (swap! a (constantly val))) > > Now, the code would certainly be cleaner if Clojure had tail-call > optimization and letrec, because you could set each algorithmic step > up as a mutually recursive function, rather than storing the steps in > a hash table, and setting up a driver loop to handle the state changes > as in a state machine. Or if Clojure just had letrec, this could be > expressed using the new trampoline construct. > > But that's not really the point. The point here is that this code > took me no effort to translate from the Knuth book, it worked on the > first run with no debugging needed, and anyone can easily compare this > code against the Knuth pseudocode, and see at a glance that this is a > correct implementation of that algorithm. There may be ways to > convert this to a functional style (and I encourage others to try it > as an interesting exercise), but with any such transformation, it will > be significantly more difficult to confirm that the program correctly > implements the algorithm. > > About half of the atom-sets are updates that could use the swap! > function, but many of these are replacing the atom's contents with > something completely unrelated to its existing contents. > > Use Case #2: setting up mutually referential data structures > > A common way to set up mutually referential data structures is to > start them off with links that are set to nil, and then use imperative > setting to direct the links at the right things. As a quick example, > consider the cyclic-linked-list solution to the classic Josephus > problem. Here is one way to set up a cyclic ring of people: > > (defn make-person [n] > {:id n, :link (atom nil)}) > > (defn link-people [p1 p2] > (atom-set (p1 :link) p2)) > > (defn ring-people [n] > (let [vec-people (vec (map make-person (range n)))] >(dotimes [i (dec n)] (link-people (vec-people i) (vec-people (inc > i >(link-people (vec-people (dec n)) (vec-people 0)) >(vec-people 0))) > > Now depending on how this is going to be used, you could argue that > maybe you're better served by refs. But if the whole point of atoms > is to give power-users another, faster choice when no coordination is > needed, why not give the programmer a choice here? If I know for sure > that I'm just going to use this ring within a single thread, or use it > internally in a function that generates and uses the ring without ever > exposing the ring outside that function, then an atom may be the right > tool for the job. > > I don't see these as being compelling arguments for atom-set. You can do these things with Java arrays or other Java things like clojure.lang.Box. OTOH, atom-set just invites the read-modify-write race conditions swap! was meant to avoid. There's simply no value for Clojure to add to a simple mutable box. Clojure does provide the tools for low-level mutation - access to Java. You can wrap that in whatever functions/macros you like. 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
Re: How to encapsulate local state in closures
On Tue, Dec 30, 2008 at 8:38 PM, Rich Hickey wrote: > There's simply no value for Clojure to add to a simple mutable box. > Clojure does provide the tools for low-level mutation - access to > Java. You can wrap that in whatever functions/macros you like. > There's no way to use the @ dereferencing syntax for a custom mutable box, right? The sample I gave would be considerably harder to read if you had to use (box-ref u) instead of @u everywhere. > OTOH, atom-set just invites the read-modify-write race conditions > swap! was meant to avoid. Yes, but not every write to an atom is going to be a read-modify-write kind of change, which is why it feels odd to always be limited to swap!. Since my examples emphasized the "simple mutable box" benefits of having atom-set, and you didn't find that compelling, let's go back to the discussion earlier in this thread about using an atom to maintain a counter that increments to generate unique IDs. You've already stated that this is one of the uses that is a good fit for atom. It would be entirely reasonable to want to, under certain conditions, to reset the counter to 0. When you reset to 0, that's just a straight write. Having to say (swap! counter (constantly 0)) feels convoluted, and somewhat obscures the fact that this change is not dependent on the previous state of the atom. Furthermore, by having to represent this reset as a swap, the counter reset might not happen as quickly as one would like. If there is a lot of contention and other threads are in the process of incrementing the counter, the reset might fail to go through for a while, because the value is frequently changed by other threads between the unnecessary read and the write of 0. An atom-set would not only reflect the intentions of the code better, but would provide better performance for the times where a read is irrelevant to the value being written. Yes, atom-set invites a certain potential for misuse, but atoms already require a certain degree of care. --~--~-~--~~~---~--~~ 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: Understanding how to use namespaces
Thanks, that helps dramatically. It took me a while to figure out how to edit the SLIME startup to include my clojure files directory in the classpath, but I got it working. So it seems like you have to make sure the namespace always matches the file. That means if you change the name of the file, you've got to remember to change the namespace declaration as well, right? Is there any way to require/use a file that has no namespace specified at the top? In Clojure Box, is there any way to make the REPL automatically "use" whatever namespaces are in the files you are actively working on? --~--~-~--~~~---~--~~ 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: Understanding how to use namespaces
On Tue, Dec 30, 2008 at 11:25 PM, Mark Engelberg wrote: > > Thanks, that helps dramatically. It took me a while to figure out how > to edit the SLIME startup to include my clojure files directory in the > classpath, but I got it working. > > So it seems like you have to make sure the namespace always matches > the file. That means if you change the name of the file, you've got > to remember to change the namespace declaration as well, right? Is > there any way to require/use a file that has no namespace specified at > the top? > > In Clojure Box, is there any way to make the REPL automatically "use" > whatever namespaces are in the files you are actively working on? > I don't know anything about SLIME or Clojure Box, but I wrote a little Clojure script that is called when I start the REPL that calls 'use' on most of the namespaces in the Clojure contrib jar. You can see the code here: http://github.com/heyZeus/clojure-stuff/tree/master/repl-init.clj > > > > --~--~-~--~~~---~--~~ 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: Stumped - Java hangs when using Swing in Slime
I would like to add that nope... installing SLIME didn't seem to help. I'm on Clojure rev. 1160, and the latest SLIME and Swank sources as of December 30 2008. --~--~-~--~~~---~--~~ 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: swank-clojure license
On 30 déc, 23:55, "Mark H." wrote: > On Dec 30, 10:26 am, Phil Hagelberg wrote: > Actually the LGPL allows linking to the library (somewhat different > than "using the code") from any program, even one which is not under > an open-source license. "L" used to stand for "library" and the > canonical example of a LGPL library is GNU's libc: any program can > link to it, and such linkage doesn't make the program have the same > license as libc. Yes, this is what I remembered concerning LPGL. But it's not the problem at hand. swank-clojure is GPL. I'm a commiter of clojure-dev, willing to embed swank-clojure clojure files in the plugin : it will be distributed with the other files. And dynamically loaded when launching a clojure JVM from the eclipse instance of a user. So swank-clojure will not be hard-linked (at compilation time) to any of clojure-dev code. Nor will it be dynamically linked to any clojure- dev code at runtime : it will be dynamically linked to the clojure environment launched by clojure-dev on behalf of the user. But, it will be distributed along with clojure-dev's code (which is under EPL license). Will I violate the GPL, if I do that ? -- Laurent --~--~-~--~~~---~--~~ 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: swank-clojure license
lpetit writes: > So swank-clojure will not be hard-linked (at compilation time) to any > of clojure-dev code. Nor will it be dynamically linked to any clojure- > dev code at runtime : it will be dynamically linked to the clojure > environment launched by clojure-dev on behalf of the user. > > But, it will be distributed along with clojure-dev's code (which is > under EPL license). > > Will I violate the GPL, if I do that ? That sounds perfectly reasonable; there shouldn't be any conflict if they're running in separate processes. >From Section 5 of the GPL: > A compilation of a covered work with other separate and independent > works, which are not by their nature extensions of the covered work, > and which are not combined with it such as to form a larger program, > in or on a volume of a storage or distribution medium, is called an > "aggregate" if the compilation and its resulting copyright are not > used to limit the access or legal rights of the compilation's users > beyond what the individual works permit. Inclusion of a covered work > in an aggregate does not cause this License to apply to the other > parts of the aggregate. -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 -~--~~~~--~~--~--~---