Re: [ANN] Envvar 1.1.0 — a library for handling environment variables
On Thursday, August 14, 2014 6:46:56 AM UTC-7, James Reeves wrote: You can do this with Environ. Leiningen checks for a profiles.clj in your project directory, as well as then one in $HOME/.lein. If you add profiles.clj to your .gitignore file, you can use it for local overrides during development and testing. Please update the Environ README to include this suggestion. The current text explicitly suggests setting variables in ~/.lein/profiles.clj, and I did not notice the reference to project-specific profiles.clj files buried deeply in Leiningen documentation. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
Re: [ANN] Envvar 1.1.0 — a library for handling environment variables
On Thursday, August 14, 2014 2:53:30 AM UTC-7, Tony Tam wrote: It wasn't really clear to me from the README why use this instead of environ. Care to explain a little more in detail? I.e. give a concrete use case. Any particular reason for not supporting .lein-env files? Also, if a .env is just a java .properties file, then why use .env files? The main distinctions from Environ are: 1. Property file .env syntax is the compatible with the one used by shells, as well as with the one used by dotenv libraries from Node and Ruby. 2. Loading env files in the REPL, and modifying the environment at runtime in general. Environ only handles loading variables when it loads itself, and has no provision for modifying them except by restarting the Clojure process. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[ANN] Envvar 1.1.0 — a library for handling environment variables
The JVM does not make using environment variables easy or convenient. The environ https://github.com/weavejester/environ library took a step in the right direction by abstracting away the distinction between environment variables and Java properties into a Clojure map data structure. However, I still found it awkward to use in multi-person projects where each programmer wants to set up different environment variable values at runtime. I also wanted an easy way to modify the environment in a dynamic scope. Hence: https://github.com/gcv/envvar Feedback welcome. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
[ANN] appengine-magic 0.4.6 released
I just released appengine-magic version 0.4.6. appengine-magic is a library which makes it easy to write Clojure web applications intended for deployment on Google App Engine. https://github.com/gcv/appengine-magic/ This version of appengine-magic adds support for Clojure 1.3.0, while retaining compatibility with 1.2.x. Other changes: I made an effort to improve support for non-Emacs interactive environments. So with luck, Clojure modes in popular Java IDEs might now work. Since I don't use these IDEs, I did not really test this, but the change I made removed an important reason why they tended to break. The datastore now has :before-save and :after-load callback support. This version of appengine-magic supports App Engine SDK 1.5.5. Please note that this release does NOT support App Engine SDK 1.6.0, released earlier today. I tried to use 1.6.0 with appengine-magic, and it introduced breaking changes to the /_ah/admin console (Google's servlets started throwing NPEs and fail to load). Unfortunately, I will not have time over the next few weeks to track down this problem. If someone sends me a working patch for this, I'll merge it in and release an update. Best, Constantine Vetoshev -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Exception handling changes in Clojure 1.3.0
I finally came up with a simple example which shows the broken exception handling behavior I described in my earlier post on this thread. (defn broken-catch [filename] (try (java.io.FileReader. filename) (catch java.io.FileNotFoundException fnfe FileNotFoundException caught) (catch RuntimeException ioe (str RuntimeException caught; cause: (.getCause ioe) user= (broken-catch /etc/passwdXYZ) RuntimeException caught; cause: java.io.FileNotFoundException: /etc/ passwdXYZ (No such file or directory) The FileReader constructor throws a FileNotFoundException when the file specified by the argument does not exist: http://download.oracle.com/javase/6/docs/api/java/io/FileReader.html#FileReader(java.lang.String) — and as you can see here, Clojure 1.3.0 wrapped it in a RuntimeException, so the expected typed catch does not work. However, if invoked in a way which bypasses reflection, the exception is properly typed: user= (try (java.io.FileReader. /etc/passwdXYZ) (catch java.io.FileNotFoundException fnfe FileNotFoundException caught) (catch RuntimeException ioe (str RuntimeException caught; cause: (.getCause ioe FileNotFoundException caught -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Exception handling changes in Clojure 1.3.0
I ran into an interesting problem while porting appengine-magic to Clojure 1.3.0. The Google App Engine SDK uses checked exceptions on many of its API methods. In many cases, I want to catch these exceptions and do something Clojure-friendly with them. With Clojure 1.2.x, I had no trouble catching checked exceptions by type, e.g.: (try (some-app-engine-api-methods-called-here ...) (catch EntityNotFoundException ex ...)) This stopped working in 1.3.0. The caught exception does not match EntityNotFoundException; it is now a RuntimeException with the original typed exception chained to it. I don't fully understand the implications of the exception handling changes in 1.3 (https://github.com/clojure/clojure/commit/ 8fda34e4c77cac079b711da59d5fe49b74605553). Does it mean that all exceptions coming in from Java code into Clojure will now be wrapped in an extra RuntimeException? If so, then typed catch clauses become useless, and the equivalent functionality will require writing code like this: (catch Exception ex (cond (isa? (class (.getCause ex)) EntityNotFoundException) ...)) I can wrap that in some kind of a catch* macro (which would also support directly catching an exception for Clojure 1.2.x compatibility), but I'm wondering if I'm doing something wrong here. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Exception handling changes in Clojure 1.3.0
On Oct 3, 12:27 pm, Stuart Halloway stuart.hallo...@gmail.com wrote: Catching checked exceptions seems to work fine. Try e.g. (try (throw (java.io.IOException.)) (catch java.io.IOException _ caught!)) I suspect something else is going wrong in the GAE example. Can you narrow the code down to a block you can quote in full here? Your example works because it doesn't trigger the use of clojure.lang.Reflector. I'm having a hard time isolating a good example where an exception passes through Reflector on its way from Java into Clojure. (It doesn't happen when trivially calling simple methods on simple Java classes.) Here is the relevant stack trace, however. The top level invocation of DatastoreServiceImpl.get throws the exception (level 0), and I hope to catch it in retrieve (level 9). 0: com.google.appengine.api.datastore.DatastoreServiceImpl.get(DatastoreServiceImpl.java: 64) 1: sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 2: sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java: 39) 3: sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java: 25) 4: java.lang.reflect.Method.invoke(Method.java:597) 5: clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:92) 6: clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:30) 7: appengine_magic.services.datastore $retrieve_helper.doInvoke(datastore.clj:363) 8: clojure.lang.RestFn.invoke(RestFn.java:521) 9: appengine_magic.services.datastore $retrieve.doInvoke(datastore.clj:376) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
[ANN] appengine-magic 0.4.0: Clojure on Google App Engine
I would like to announce the release of appengine-magic version 0.4.0, a library designed to make it easier to write Clojure applications for Google App Engine. appengine-magic abstracts away nearly all the boilerplate necessary to deploy an App Engine application. It also enables interactive development through the REPL. It has full support for most App Engine services: the datastore, memcache, user Google account authentication, the blobstore, sending and receiving email, task queues, image processing, remote URL access, and server push. 0.4.0 is a significant improvement over previous versions, and includes: - Support for the latest App Engine SDK. - Support for all App Engine API operations in the interactive REPL, as long as the application is running. This includes all datastore and memcache operations. - Support for using the /_ah/admin console when running in interactive REPL mode. - Support for deploying applications with multiple environments (e.g., production and staging can be deployed separately from the same project.clj definition). - Bindings for the App Engine image processing API. - Bindings for server push (Channel API). https://github.com/gcv/appengine-magic The library is available in Clojars. The README file fully documents the available API. Please note that this release includes several minor breaking changes; they are detailed in the HISTORY file. Comments, bug reports, questions, and patches welcome. Thanks, Constantine Vetoshev -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Help - .class files and GAE's too many files problem
On Feb 10, 7:47 pm, Edgar Gonçalves edgar.goncal...@gmail.com wrote: So for future reference, if you come up with the same issue, the solution is to compile your gen'ed-classes and delete all the others from the war/WEB-INF directory, making sure you have a standalone jar along the remaining used jars (a uberjar may also work, can't see why not). If you happen to have a file-size problem on your jars, you can use a flag on the upload script. Google for --enable_jar_splitting for more details. I realize you already solved the problem in your app, but for the benefit of others reading this thread: appengine-magic takes care of this for you. It bundles loose class files into you application's .jar. This has the added benefit of making deployment much faster. Unless you need AOT compilation for gen-class, you never have to worry about managing compiled files. http://github.com/gcv/appengine-magic -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Library and development process for GAE
On Jan 9, 10:54 am, Stefan Kamphausen ska2...@googlemail.com wrote: Given that decision I'd like to understand the general development process. Does one always compile to a class (ns ...gen-class ..extends ..Servlet) and will the appengine development server pick up the changes, or will I just recompile a function (using a setup with Emacs and SLIME), what about the REPL mode of appengine-magic together with the datastore and other features. I'm the author of appengine-magic, so my opinion is necessarily biased in its favor. :) appengine-magic is designed to be a self-contained, easy way to use Google App Engine with Ring, or any Ring-compliant framework. appengine-magic includes its own datastore abstraction layer, with a (reasonably) high-level Clojure syntax and API. Most other App Engine services are also included, with idiomatic Clojure wrappers. I optimized the development process for interactive use. You write code with Emacs and SLIME, recompile functions interactively, and your local development web server will show all changes. No restarts and no nasty watch this directory for changed class files kludges are needed. In version 0.4.0 (https://github.com/gcv/appengine-magic/tree/ v0.4.0, use 0.4.0-SNAPSHOT as a dependency), the REPL mode works fine with the datastore and other App Engine SDK features: you can run datastore queries right from the REPL. I will probably finalize the 0.4.0 release soon, since it's a huge improvement over 0.3.x. For deployment, you will have to compile .class files, but appengine- magic provides Leiningen tasks to simplify the process. Please refer to the documentation for more information, but you basically just run lein appengine-prepare and then either run the SDK's deployment script or lein appengine-update. The README file has full instructions for getting started. To get started, just install the SDK and make a Leiningen project with the correct dependencies. Feel free to contact me if you have any questions. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Automatically unmapping unit tests from namespaces
On Dec 21, 7:16 pm, Phil Hagelberg p...@hagelb.org wrote: If you're already using swank then you can try clojure-test-mode; it clears out all deftests in between test runs. https://github.com/technomancy/clojure-mode/blob/master/clojure-test-... It also highlights failures in the test buffer for better feedback. clojure-test-mode is pretty nice, but is there any way to make its test namespace naming convention configurable? It currently expects src/com/company/project/file.clj to correspond to test/com/company/project/test/file.clj. I prefer test/test/com/company/ project/file.clj, i.e., just prefix the whole namespace with test, rather than insert it as the penultimate namespace element. I find it much easier to tell, at a glance, if I'm looking at a test namespace if it just starts with test, rather than hunting through the entire dotted string. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ANN: Dr. Evil - the evil web debugger
On Nov 29, 2:25 pm, Miki miki.teb...@gmail.com wrote: Yeah, it uses load-string which IMO default to clojure.core namespace. I've tried some namespace hacking to allow the user to define the namespace, but couldn't make it work (there's a FIXME in the code about that). Currently I using names with namespace - (cv-test-1.core/some-func arg1 arg2). Will try to fix that soon. Could (eval (read-string ...)) work? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ANN: Dr. Evil - the evil web debugger
On Nov 22, 6:43 pm, Miki miki.teb...@gmail.com wrote: Dr.Evilis a simple web debugger that provides a REPL to your web application in a hidden location. This is pretty useful, thanks! I tried adding Dr. Evil into a test app, but I'm having trouble switching namespaces in the REPL: = *ns* #Namespace clojure.core = (in-ns 'cv-test-1.core) #Namespace cv-test-1.core = *ns* #Namespace clojure.core It seems to always reset the namespace to clojure.core. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: appengine-magic 0.3.0: Clojure on Google App Engine
On Nov 24, 6:41 am, Vesa Marttila vtmartt...@gmail.com wrote: I have a question about this release: I understood from this release announcement that entities can be saved from the REPL, but I was not able to do so and the official documentation still states that it can't be done, which is the case? You can't directly use datastore functions from the REPL. When I said interactive development through the REPL, I meant the ability to recompile individual files and functions inside a running application — this definitely works across the board; it was a design requirement for appengine-magic. You need to use an editor-linked REPL for this functionality, such as SLIME. I believe VimClojure, Enclojure (NetBeans), Counterclockwise (Eclipse), and La Clojure (IntelliJ IDEA) should also work, but do not use them myself. That said, I hear you loud and clear. Several other people have asked me about making it possible to use the datastore from the REPL. I actually tried to get that into this release, but it requires a decent amount of hackery. I'll see what I can do about putting this into the next release. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
[ANN] appengine-magic 0.3.0: Clojure on Google App Engine
I would like to announce the release of appengine-magic version 0.3.0, a library designed to make it easier to write Clojure applications for Google App Engine. appengine-magic abstracts away nearly all the boilerplate necessary to deploy an App Engine application. It also enables interactive development through the REPL. The new version has full support for many App Engine services: the datastore, memcache, user Google account authentication, the blobstore, sending and receiving email, task queues, and remote URL access. http://github.com/gcv/appengine-magic The library is available in Clojars. The README file fully documents the available API. Comments, bug reports, questions, and patches welcome. Thanks, Constantine Vetoshev -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: appengine-magic: using Clojure with Google App Engine
On Oct 4, 10:52 pm, Glen Stampoultzis gst...@gmail.com wrote: On 21 September 2010 07:15, Constantine Vetoshev gepar...@gmail.com wrote: I'd like to announce the release of a working version of appengine- magic, a library designed to make it easier to get started with Google App Engine using Clojure. .. chop .. I noticed it uses ring out of the box. I was wondering if this is compatible with compojure? There also seems to be a compojure-gae project floating around so I'm a little confused as to which project I should be using. appengine-magic works well with Compojure (version 0.5.x). Any Ring- compatible framework should also work, as long as it has no dependencies blacklisted in the App Engine classloader. I should probably put an example in the documentation, but here's one in the meanwhile: (use 'compojure.core) (require '[appengine-magic.core :as ae]) (defroutes test-1-app-handler (GET / [] hello world) (ANY * [] {:status 404 :headers {Content-Type text/plain} :body not found})) (ae/def-appengine-app test-1-app #'test-1-app-handler) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
VerifyError with symbol metadata, macros, and defrecord
In Clojure 1.2, compiling the code below blows up with: error: java.lang.VerifyError: (class: t1/core/One, method: clinit signature: ()V) Incompatible argument to function (core.clj:11) Something about this problem causes damage to the running Clojure process. Once the exception happens, changing the macro to a working version will not make the sample work with the tagged symbol, almost as if the symbol 'one (below) is somehow corrupt. You either need to start a new REPL, or try to invoke the macro with a different tagged symbol. I'm honestly not even sure if (1) I don't understand something, (2) this is a bug in Clojure, or (3) this is just a remarkably unhelpful error message. (ns t1.core) (defmacro mac1 [name properties] ;; does not work: (let [key-info (keyword (first (filter #(meta %) properties)))] ;; works: ;(let [key-info (keyword (str (first (filter #(meta %) properties] (prn key-info) ;; commenting out the defrecord below also makes this work: `(defrecord ~name ~properties))) (mac1 One [^:key one, two]) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Making Clojure really work with Google App Engine
On Sep 20, 9:17 am, Stefan Kamphausen ska2...@googlemail.com wrote: So it might be a good idea to avoid creating threads automatically or importing file/socket packages. I think you're right. Dependencies are always a double-edged sword, and in the case of App Engine, they are more toxic than usual. Anyway, I eliminated the ring-servlet dependency, and appengine-magic now successfully deploys simple hello world Ring applications. I'll send a more formal announcement to the mailing list shortly. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
[ANN] appengine-magic: using Clojure with Google App Engine
I'd like to announce the release of a working version of appengine- magic, a library designed to make it easier to get started with Google App Engine using Clojure. appengine-magic abstracts away nearly all the boilerplate necessary to deploy an App Engine application. It also enables interactive development through the REPL. http://github.com/gcv/appengine-magic The library is available on Clojars. It does not currently provide any App Engine services, but I wanted to get a usable version out as quickly as possible. Please look through the README file for details. Comments welcome, as always. Constantine Vetoshev -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Making Clojure really work with Google App Engine
I recently spent some time trying to abstract away some of the incidental complexity of using Google App Engine with Clojure. Right now, setting up interactive development and understanding what to do requires reading several blog posts, and pasting in a lot of boilerplate code. I ended up making a small library, called appengine- magic, which cuts the boilerplate down to (1) a single additional .jar dependency, (2) a couple of macros, and (3) a couple of files generated by a Leiningen plugin. It takes a Ring handler, and turns it into an application suitable for App Engine. http://github.com/gcv/appengine-magic It doesn't do everything yet, but I feel that it already makes a much easier starting point than any alternative. The README file explains the details. Unfortunately, I hit a major stumbling block. Live deployment to App Engine does not work because of a dependency importing a blacklisted class. appengine-magic expects to deploy a Ring handler. This makes it possible to write apps using any Ring-compliant Clojure web framework. In order to deploy to App Engine, it needs to turn the handler into a servlet. The ring-servlet library does this with its handy ring.util.servlet/defservice function. The implementation of defservice uses duck-streams/copy. duck-streams imports java.net.Socket, a class blacklisted by App Engine, causing deployment to fail. So any innocuous dependency, which transitively depends on anything which loads a file which imports a blacklisted class, can cause deployment to fail. Even Clojure itself is not entirely safe: for example, duck-streams is now clojure.java.io, which imports java.net.Socket. I can reimplement defservice, and so avoid depending on ring-servlet. Still, the situation seems fragile and precarious. Suggestions and comments welcome. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Extending Clojure's STM with external transactions
On Sep 5, 8:56 pm, Alyssa Kwan alyssa.c.k...@gmail.com wrote: Any thoughts on how to marshal functions? What about vars and dynamic binding? I don't think marshaling closures will ever happen without changes to Clojure itself. I haven't looked into how much work it would require, or how much it would impact Clojure's performance. It always seemed like an excessively lofty goal anyway: if I could save plain Clojure data structures (all primitives, all fully-evaluated collections, and all records), I would be happy with it. In truth, I always wanted to extend Cupboard to support some kind of semi-magical distributed storage (like Oracle Coherence, but with better persistence guarantees — database-like rather than cache-like), but wanted to get single-node basics working properly first. The latest BDB JE has some replication built-in, and I planned to use it. As for dynamic binding, I'm not sure what you mean. The bound value will evaluate using Clojure's normal rules when cupboard.core/make- instance runs, and go into the database. cupboard.core/query will then read it and make the value part of the returned map (it should really be a Clojure 1.2 record). The code doesn't do anything except save and restore fully-evaluated data structures. Incidentally, Cupboard wraps BDB transactions, and does not attempt to work with Clojure's STM subsystem. I always considered this a weakness, but a difficult one to resolve. To counterbalance it, I planned to avoid mixing STM and on-disk data structures in the same code. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Extending Clojure's STM with external transactions
On Aug 30, 5:02 pm, nchubrich nchubr...@gmail.com wrote: Persistence libraries always end up warping the entire codebase; I've never succeeded in keeping them at bay. Using data with Incanter is different from ClojureQL, which is different from just using contrib.sql, and all of it is different from dealing with just Clojure. (I've never even tried Clojure + Hibernate.) You might as well rewrite the program from scratch depending on what you use. Maybe other people have had better luck; but whatever luck they have, I'm sure it is a fight to keep programs abstracted from persistence. I feel the same way. Late last year, I wrote a small BDB-based library for adding disk persistence to Clojure datatypes. It does require knowing in advance which types you want to write to disk. I haven't had time to work on it recently, but I'd like to pick it up again sometime soon. (And I welcome help — the wonders of open-source software and all that.) http://github.com/gcv/cupboard It has a few outstanding problems. 1. It needs to be updated for deftype and defrecord in Clojure 1.2. 2. Deadlock detection doesn't seem to work 100% of the time, and I haven't yet tracked down the reasons. Parts of the test suite currently fail as a result. 3. Reads are slow. Casual profiling hasn't revealed the reasons, so it's a bit tricky to track down. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: My non-ELPA Emacs swank-clojure setup
On Apr 8, 12:45 pm, Ævar Arnfjörð Bjarmason ava...@gmail.com wrote: If I have 10 Clojure projects I'm going to have 10 src/clojure.jar files. Do they really need to be there or could I just use the clojure that comes with my operating system (Debian)? When I hack Common Lisp I don't copy sbcl into all my projects, I just install it once globally. I'd like to do the same with clojure. Although I'm with you about ELPA and preferring the traditional way to install Emacs packages, I disagree on this point. I find it counterproductive to think of Clojure and its distribution in the same terms as Common Lisp's. It's easier to think of Clojure apps more like Java apps which happen to use a much better language. I actually prefer to have a lib/clojure-X.Y.Z.jar in my project. This guarantees that, as long as the deployment machine has a Clojure- supporting JVM, the app has no other system-level dependencies. It also allows flexibility with trying out unreleased and unpackaged versions of Clojure. This eliminates the hideous mess in most distributions of having packages like python24, python25, python26, python30 (and resulting things like python24-somelib and python26- somelib). -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: My non-ELPA Emacs swank-clojure setup
This thread encouraged me to post what I did to make swank-clojure 1.1.0 work with the the latest SLIME. It does not use any of swank- clojure's automatic .jar downloading features (as of version 1.1.0). These instructions won't work on Windows, but may work if you have Cygwin. Note that this sets up some Common Lisp installations. Delete those lines if you don't want them. If you already figured out how to put SLIME and swank-clojure on your classpath, omit that part of the setup. See the comments. Assumptions: - SLIME in ~/.emacs.d/site-lisp/slime - swank-clojure in ~/.emacs.d/site-lisp/swank-clojure - your project is laid out with a src/ directory containing your actual code; it goes on the classpath - you want all .jar files in your project on your classpath - several directories, including classes/ and resources/, also get added to your classpath - you have exactly one file called clojure-version-number.jar in the resulting classpath; this becomes the version of Clojure launched by SLIME Instructions: - put the code below into your .emacs.d/init.el or .emacs file - use M-x clojure-project to launch SLIME; this is my variant of swank-clojure-project, but it makes no assumptions about Maven, magical downloads, ELPA, or anything else Limitation: - slime-connect doesn't seem to work right; you have to launch Clojure and your app using clojure-project One more thing: swank-clojure 1.1.0 requires a tiny patch to work with the latest SLIME. This patch seems to already be in swank-clojure's master branch, but be aware of it: http://groups.google.com/group/swank-clojure/msg/01ff818359061a28 Could this be a good start to making swank-clojure both newbie-and- ELPA-friendly and Emacs-graybeard-friendly? ;;; generic Emacs utility ;;; -- (defun add-subdirs-to-load-path (dir) (let ((default-directory (concat dir /))) (normal-top-level-add-subdirs-to-load-path))) ;;; basic load-path setup ;;; -- (add-to-list 'load-path ~/.emacs.d/site-lisp) (add-subdirs-to-load-path ~/.emacs.d/site-lisp) ;;; SLIME and swank-clojure ;;; -- (require 'slime-autoloads) (add-to-list 'load-path ~/.emacs.d/site-lisp/slime/contrib) ;(slime-setup '(slime-fancy slime-asdf)) (slime-setup '(slime-repl)) (setq slime-net-coding-system 'utf-8-unix) (setq slime-lisp-implementations '((acl (/opt/acl/alisp)) (sbcl (/opt/sbcl/run-sbcl.sh)) (ccl (/opt/ccl/dx86cl64 (defmacro defslime-start (name mapping) `(defun ,name () (interactive) (let ((slime-default-lisp ,mapping)) (slime (defslime-start acl 'acl) (defslime-start sbcl 'sbcl) (defslime-start ccl 'ccl) (defslime-start clojure 'clojure) (setq swank-clojure-classpath '(~/.emacs.d/site-lisp/swank-clojure/ src)) (setq swank-clojure-extra-vm-args (list -server -Xms128M -Xmx512M -Dfile.encoding=UTF-8)) (autoload 'clojure-mode clojure-mode A major mode for Clojure t) (add-to-list 'auto-mode-alist '(\\.clj$ . clojure-mode)) (require 'swank-clojure) (add-hook 'slime-mode-hook (lambda () (setq slime-truncate-lines nil) (slime-redirect-inferior-output))) (defun clojure-slime-reset () Helper function which resets Clojure in SLIME's list of implementations. Useful for changing Clojure's classpath. (setq slime-lisp-implementations (cons `(clojure ,(swank-clojure-cmd) :init swank-clojure-init) (remove-if #'(lambda (x) (eq (car x) 'clojure)) slime-lisp-implementations (defun clojure-project-prompt (path) (interactive GProject path: ) (list path)) (defun clojure-project (path) Set up Clojure classpath and other swank-clojure variables for the project with root at 'path'. Include all *.jar files under path. Also include 'classes' subdirectory. (interactive (let* ((dominating-file (locate-dominating-file buffer-file-name src/)) (default-directory (if (and buffer-file-name dominating- file) dominating-file default-directory))) (call-interactively 'clojure-project-prompt))) (when (and (fboundp 'slime-connected-p) (slime-connected-p)) (slime-quit-lisp) (sleep-for 1) (slime-kill-all-buffers)) (flet ((clojure-jar-p (s) (string-match clojure\\(-[0-9a-f\\.]*\\)?\\.jar$ s)) (validate-path (p) (when (file-accessible-directory-p p) (list p (let* ((src-path (append (validate-path (expand-file-name src path)) (validate-path (expand-file-name source path)) (validate-path (expand-file-name code path (test-path
Re: Clojure for financial applications
On Mar 8, 11:50 am, Jonathan Shore jonathan.sh...@gmail.com wrote: How would I encapsulate this into a data structure to be passed into functions efficiently? I could use a map of symbols to various structures, but that would be inefficient in access and memory. I could bind into a closure but then how do I evolve the closure. Doug Hoyte's book Let Over Lambda (http://letoverlambda.com) has plenty of tips on how to hack closures, including accessing closed- over values. The book uses Common Lisp, but most of it maps easily to Clojure. The relevant chapter on anaphoric macros is not available in the free preview, unfortunately. To summarize in Clojure terms, you make a wrapper macro for fn, called, e.g., pfn. pfn then works exactly like fn, except you may also use it with some predetermined arguments. Those arguments make the closure return closed-over values. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Prepping clojure for packaging (was: Re: Clojure for system administration)
On Feb 6, 1:06 pm, Peter Schuller peter.schul...@infidyne.com wrote: But the practical issue remains that if I want to write some software that I want sysadmins in various situations to want to use effortlessly (in my case, a backup tool), problems like these do get in the way of choosing Clojure. Maybe uberjars are the pragmatic approach after all. But then what about GPL libraries and similar license hassles? I can't comment on the licensing problem, but could you expand on what exactly you don't like about packaging jars (as uberjars or separates) and distributing them as part of your application? If you distribute your app with precisely the jars you tested with, you don't have to worry about subtle incompatibilities sneaking in. Except for obviously bloated software (e.g., JBoss), Java jar files are relatively small. When you package for Debian, put the jars in /usr/share/my-awesome-app/ jars, put in a dependency on sun-java-1.x, and provide a wrapper shell script to start the whole thing (your classpath just includes the stuff you provided). For the installing admin, your package is just an aptitude install my-awesome-app away, and it just pulls down a JVM dependency. Simple, and fairly lightweight. I stopped using Python and Ruby and Perl partly because the packaging situation for all those languages is a horrible mess. For example, if you write a Ruby app, you are highly likely to run into trouble packaging it even for a recent distribution because your dependencies may not have been packaged or made available as rb-*.debs in the official repository. Or, rb-*.debs exist, but provide an incompatible version of the library you need. Ubuntu and Fedora may ship different versions of common gems, so you can't even code against an obvious lowest common denominator. (To make matters worse, gem install, easy_install, and cpan -i all create weird parallel universes of packages which may cause conflicts with system-provided packages. Python's virtualenv helps mitigate the problem to some extent.) C programs have it easier, because the overwhelming majority of commonly used libraries are packaged and available in recent distributions, and I have rarely had trouble with just writing against a slightly older version of a library. It's perfectly reasonable to dynamically link against libjpeg and make a note of a libjpeg dependency in the package descriptor file. In short, I think that the Java and Clojure way of packaging software make life much easier for programmers, package maintainers, and administrators, not harder. Making applications self-contained helps avoid dependency hell at packaging and deployment time, not to mention during development. It's a bit wasteful to have multiple copies of log4j or whatever floating around, but I'd rather waste a few gigabytes of disk space on duplicates than deal with system-wide classpaths. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ANN: dgraph 1.0, a dependency graph library for Clojure
On Jan 18, 2:14 am, mac markus.gustavs...@gmail.com wrote: Updating stuff in the map became a little bit of a hassle so I made versions of assoc-in and update-in that work on dgraphs. Here they are in case anyone else is interested: (defn assoc-node [dgraph m ks v] (dgraph m (assoc-in (dgraph m) ks v))) (defn update-node [dgraph m ks f args] (dgraph m (apply update-in (dgraph m) ks f args))) Suppose we have a dgraph dg and a map in the dgraph with the key :gui- data, in the map we want to replace or update the key :message (assoc-node dg :gui-data [:message] Hello World!) (update-node dg :gui-data [:message] conj World!) Thanks, Markus! I added these functions into dgraph as assoc-in-node and update-in-node. The new version of dgraph with these additions is 1.1.0, available on GitHub and Clojars. http://github.com/gcv/dgraph http://clojars.org/dgraph -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ANN: dgraph 1.0, a dependency graph library for Clojure
On Jan 17, 4:05 am, Albert Cardona sapri...@gmail.com wrote: The link gives a not found--did you push? I did, but then I moved the examples directory around to make everything more Leiningen-layout-friendly. Here is the updated link: http://github.com/gcv/dgraph/blob/master/examples/examples/dgraph/swing.clj Please note that navigating the tree from the GitHub web interface has strange redirect bugs right now. I opened a ticket with GitHub to investigate the problem. Cloning the repository works fine. By the way dgraph looks really interesting for GUI programming. I am looking forward to trying it out. Great! Let me know how it works out for you. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ANN: dgraph 1.0, a dependency graph library for Clojure
On Jan 16, 4:01 am, mac markus.gustavs...@gmail.com wrote: I am just now in a situation where I have to do some swing programming and this seems like it has great potential! Since it's already version 1.0 you should put it on Clojars so that it is easier to use from leiningen or maven etc. Good call. I just put it up on Clojars: http://clojars.org/dgraph. Let me know how using dgraph works out for you. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ANN: dgraph 1.0, a dependency graph library for Clojure
On Jan 14, 7:29 pm, Timothy Pratley timothyprat...@gmail.com wrote: To give me a head-start, are there key differences with clojure.contrib.dataflow so I can better understand? Thank you for your interest. I have not extensively used c.c.dataflow, so I apologize if I misrepresent it, but here are some key differences: 1. c.c.dataflow feels imperative in nature. build-dataflow returns a ref. Functions which manipulate these refs — such as update-values, add-cells, and remove-cells — use destructive modification. dgraph tries pretty hard to work functionally, just like Clojure's built-in persistent data structures. A dgraph is immutable, but supports an extend operation similar to assoc and conj. Extended dgraphs share structure with original dgraphs as much as possible. 2. c.c.dataflow does not seem to support lazily computed nodes. A node put in a dataflow computes itself immediately. dgraph supports this behavior with eager nodes, but has two other modes: lazy and patient. I tried to explain how those work in the README. Please let me know if the documentation makes no sense. I'll add a more detailed example to the source repository later today. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ANN: dgraph 1.0, a dependency graph library for Clojure
On Jan 15, 5:59 am, Laurent PETIT laurent.pe...@gmail.com wrote: I would like to know, is there an essential reason for not having stored the dependency graph as a hidden property of the graph ? I'm not sure I understand your question. You can see the stored graph if you take the function returned by dg/make-dgraph and call it without any arguments. I consider that an implementation detail, though. The dependency graph returned by dg/make-graph is a closure rather than a data structure mainly to allow shortcut syntax for accessing and setting node values: (my-dgraph :my-node) is just a function call. So is (my-dgraph :my-node new-node-value). If my-dgraph was not a function, there would have to be a more verbose calling convention. (Reader macro support in Clojure would have taken away some of the verbosity.) Do you have examples of where you see it interesting to use (and not abuse :-) ) side effects in combination with eager/patient ? I just checked in a Swing usage example which uses side effects to update the UI (http://github.com/gcv/dgraph/blob/master/src/examples/ dgraph/swing.clj). Please let me know if it makes sense. I hope the concept is useful outside of just making Swing programming less agonizing, though. :) Are there implicit hypothesis (not yet documented ? or maybe I overlooked) on the types that can be used for the keys of the graph ? Not particularly, no. I have always used keywords, so they are best- tested. Even so, any type usable as a key in a normal Clojure map should work. If you find something not working with another type, definitely let me know, and I'll try to fix it. For those of use who do not know cl cells, would it be easy to explain in which area it differs ? Cells the Common Lisp library lets you put slots of CLOS objects on a dependency graph. Put another way, any slot in any CLOS object can become a node on the graph. The Clojure dgraph library isolates the entire dependency graph in a separate, immutable data structure. Clojure cannot readily adopt the Cells way of doing things, because it has no CLOS and no meta-object protocol. dgraph also tries to at allow and even encourage purely functional use, in spite of its usefulness in side-effect-ridden UI code. Cells is more imperative in nature. Thanks for your interest in dgraph! -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
ANN: dgraph 1.0, a dependency graph library for Clojure
I would like to announce the release of dgraph 1.0, a dependency graph implementation for Clojure. http://github.com/gcv/dgraph dgraph provides a mostly pure functional data structure whose nodes behave like cells in a spreadsheet. Data changes in stored nodes cause their dependent computed nodes to invalidate and recalculate themselves. Dependency graphs are immutable, just like Clojure's built- in persistent data structures, so changing a stored node actually augments an existing graph and returns a new one with shared structure. I wrote this to simplify UI programming, and it has helped reduce the pain significantly. The README file in the GitHub repository has some usage examples and ideas. Comments and bug reports welcome. Thanks, Constantine Vetoshev -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Clojure + Redis
On Dec 30, 10:40 am, Robert Campbell rrc...@gmail.com wrote: I think anything which lowers the impedance mismatch between Clojure data structures and a persistent store is worth investigating. I'd love to find an ACID, transactional store which accepts native structures. Have you looked at Cupboard (http://github.com/gcv/cupboard)? It tries to make it easy to store native Clojure data structures, and it is as ACID and transactional as the underlying Berkeley DB JE implementation. If you have looked at it, I'd appreciate some feedback as to where it fell short of your expectations. :) I plan to start adding distributed storage support in the next few months. The latest JE release has master-slave replication, which I think will work well for Cupboard. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Clojure as a first programming language?
On Dec 1, 12:38 am, Towle towle.m...@gmail.com wrote: So after shopping around thoroughly and picking up bits about on theoretical computer science and the history of programming languages, I decided to pick up a Lisp; I'm intrigued by the greater concept/idea behind the Lisp family of languages. In your research, did you find Abelson and Sussman's book, Structure and Interpretation of Computer Programs? The full text is freely available at http://mitpress.mit.edu/sicp/, and video lectures from the class are at http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/. I have never seen a better introduction to programming and computing than SICP. It uses Scheme, but you do not need to study the language separately; you'll learn it naturally as you go through the book. Be sure to do the exercises. :) You can certainly go through SICP using Clojure, but you'll have to deal with semantic differences between Scheme and Clojure (especially in laziness and sequence behavior), so I don't recommend it. After you have gone through the book, you'll pick up Clojure in no time at all, and will probably find it an enjoyable language for real-world programming. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: A macro for flexible keyword argument handling
On Nov 20, 8:33 am, nchubrich nicholas.chubr...@gmail.com wrote: I guess this is getting to be a pretty epic macro! I figured it was worth inviting boos and/or cheers and suggestions before setting out... Far be it from me to discourage making function invocation semantics more flexible! Just one thing: you've been calling your macro defnsk, which makes it sound like a wrapper for the def form. Don't leave defmethod, fn, letfn, and every other way of making a function in the dust. :) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: A macro for flexible keyword argument handling
On Nov 17, 11:33 pm, nchubrich nicholas.chubr...@gmail.com wrote: can it be any more general or minimal than this? Seems to me that your suggestion effectively makes every positional argument optional. You did note that the scheme calls for supplied- predicates, but this pushes responsibility for checking required arguments from the compiler to the programmer. That seems a little too minimal to me, and barely an improvement from extracting everything from an arguments array. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: A macro for flexible keyword argument handling
On Nov 16, 4:28 pm, Chouser chou...@gmail.com wrote: 'let' is also careful to always have the user provide the symbol being bound as a symbol. That is you say {:keys [a b c]} not {:keys [:a :b :c]}. What do you think of having let-kw take symbols instead of keywords for the names being bound? I think that's a good idea. Updated version: (defmacro let-kw Adds flexible keyword handling to any form which has a parameter list: fn, defn, defmethod, letfn, and others. Keywords may be passed to the surrounding form as rest arguments, lists, or maps. Lists or maps must be used for functions with multiple arities if more than one arity has keyword parameters. Keywords are bound inside let-kw as symbols, with default values either specified in the keyword spec or nil. Keyword specs may consist of just the bare keyword symbol, which defaults to nil, or may have the general form [keyword-name keyword-default-value* keyword-supplied?*]. keyword-supplied? is an optional symbol bound to true if the keyword was supplied, and to false otherwise. [kw-spec-raw kw-args body] (let [kw-spec (map #(if (sequential? %) % [%]) kw-spec-raw) symbols (map first kw-spec) keywords (map (comp keyword name) symbols) defaults (map second kw-spec) destrmap {:keys (vec symbols) :or (zipmap symbols defaults)} supplied (reduce (fn [m [k v]] (assoc m k v)) (sorted-map) (remove (fn [[_ val]] (nil? val)) (partition 2 (interleave keywords (map (comp second rest) kw-spec) kw-args-map (gensym)] `(let [kw-args# ~kw-args ~kw-args-map (if (map? kw-args#) kw-args# (apply hash-map kw-args#)) ~destrmap ~kw-args-map] ~@(if (empty? supplied) body `((apply (fn [~@(vals supplied)] ~...@body) (map (fn [x#] (contains? ~kw-args-map x#)) [~@(keys supplied)]))) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: SLIME REPL broken
On Nov 17, 2:52 pm, David Nolen dnolen.li...@gmail.com wrote: Thanks for pursuing this so adamantly :) For a long time (more than a year) it was possible to use SLIME tip. It would be great for that to continue. You can still use SLIME; just avoid the slime-autodoc contrib. Use (slime-setup '(slime-repl)) to initialize SLIME. At least, this works for me. Make sure you don't use (slime-setup '(slime-fancy)), because slime-fancy includes slime- autodoc. You lose the nicer minibuffer function argument display, but at least the basic environment works. -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: A macro for flexible keyword argument handling
1. Looks like everyone prefers the let-kw name. Sounds good to me. 2. I tried it with the more let-like form, but I don't like the number of opening braces required. For a full kw-spec, the form would end up (let-kw [[[:kw default supplied?]] kw-args] ...). Clojure tends to err on the side of fewer braces and parentheses, and three opening braces looks excessive to me. That said, I see the point of keeping it consistent with the other binding forms. 3. Unnecessary interleave replaced with zipmap. 4. With regard to the generality of the interface: I put all those features in there because I have wanted to use them. I often find myself writing or wrapping API-like code, and slicing and dicing arguments and passing them through to other functions, as vectors or maps, has been useful. 5. As for putting the macro in clojure-contrib, thanks for the vote of confidence. :) I'll drop a signed Contributor Agreement in the mail today, and get an Assembla ticket and patch out soon. Thanks for all the feedback and suggestions. New version: (defmacro let-kw Adds flexible keyword handling to any form which has a parameter list: fn, defn, defmethod, letfn, and others. Keywords may be passed to the surrounding form as rest arguments, lists, or maps. Lists or maps must be used for functions with multiple arities if more than one arity has keyword parameters. Keywords are bound inside let-kw as symbols, with default values either specified in the keyword spec or nil. Keyword specs may consist of just the bare keyword, which defaults to nil, or may have the general form [:keyword-name keyword-default-value* keyword-supplied?*]. keyword-supplied? is an optional symbol bound to true if the keyword was supplied, and to false otherwise. [kw-spec-raw kw-args body] (let [kw-spec (map #(if (sequential? %) % [%]) kw-spec-raw) keywords (map first kw-spec) symbols (map (comp symbol name) keywords) defaults (map second kw-spec) destrmap {:keys (vec symbols) :or (zipmap symbols defaults)} supplied (reduce (fn [m [k v]] (assoc m k v)) (sorted-map) (remove (fn [[_ val]] (nil? val)) (partition 2 (interleave keywords (map (comp second rest) kw-spec) kw-args-map (gensym)] `(let [kw-args# ~kw-args ~kw-args-map (if (map? kw-args#) kw-args# (apply hash-map kw-args#)) ~destrmap ~kw-args-map] ~@(if (empty? supplied) body `((apply (fn [~@(vals supplied)] ~...@body) (map (fn [x#] (contains? ~kw-args-map x#)) [~@(keys supplied)]))) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
A macro for flexible keyword argument handling
A couple of days ago, I finally had enough of manually extracting function keyword arguments. defnk is cool and all, but it does nothing for fn, letfn, defmethod, or any other form with a parameter list. Map destructuring is also cool, but providing defaults requires writing each symbol twice, once in :keys and once in :or. The macro I ended up with, fn-keywords, owes much to Common Lisp's lambda lists. Instead of an outer wrapper for Clojure's various function forms, it provides a kind of inner wrapper, really a let form specialized for keyword arguments. Each keyword is defined in a keyword spec, which allows for an optional default value, and for an optional symbol to be bound to true if the keyword was actually provided in the function call. Note that keywords arguments may be rest in style, or provided as either maps or vectors. This should cover all useful cases for keyword arguments, including their use in functions with multiple arities. Example: (defn test1 [req1 req2 kw-args] (fn-keywords [:kw1 [:kw2 kw2 default] [:kw3 kw3 default kw3-supplied?]] kw-args ;; function body {:req1 req1 :req2 req2 :kw1 kw1 :kw2 kw2 :kw3 kw3 :kw3-supplied? kw3-supplied?})) (test1 1 2 :kw3 there) {:req1 1, :req2 2, :kw1 nil, :kw2 kw2 default, :kw3 there, :kw3-supplied? true} (test1 1 2 :kw1 there) {:req1 1, :req2 2, :kw1 there, :kw2 kw2 default, :kw3 kw3 default, :kw3-supplied? false} (test1 1 2 :kw1 hello :kw2 there) {:req1 1, :req2 2, :kw1 hello, :kw2 there, :kw3 kw3 default, :kw3-supplied? false} Macro code: (defmacro fn-keywords Adds flexible keyword handling to any form which has a parameter list: fn, defn, defmethod, letfn, and others. Keywords may be passed to the surrounding form as rest arguments, lists, or maps. Lists or maps must be used for functions with multiple arities if more than one arity has keyword parameters. Keywords are bound inside fn-keywords as symbols, with default values either specified in the keyword spec or nil. Keyword specs may consist of just the bare keyword, which defaults to nil, or may have the general form [:keyword-name keyword-default-value* keyword-bound?*]. keyword- bound? is an optional symbol bound to true if the keyword was supplied, and to false otherwise. [kw-spec-raw kw-args body] (let [kw-spec (map #(if (sequential? %) % [%]) kw-spec-raw) keywords (map first kw-spec) symbols (map (comp symbol name) keywords) defaults (map second kw-spec) destrmap {:keys (vec symbols) :or (apply hash-map (interleave symbols defaults))} supplied (reduce (fn [m [k v]] (assoc m k v)) (sorted-map) (remove (fn [[_ val]] (nil? val)) (partition 2 (interleave keywords (map (comp second rest) kw- spec) kw-args-map (gensym)] `(let [kw-args# ~kw-args ~kw-args-map (if (map? kw-args#) kw-args# (apply hash-map kw-args#)) ~destrmap ~kw-args-map] ~@(if (empty? supplied) body `((apply (fn [~@(vals supplied)] ~...@body) (map (fn [x#] (contains? ~kw-args-map x#)) [~@(keys supplied)]))) More examples: (defmulti test2 (fn [x rest] (class x))) (defmethod test2 java.lang.Integer [req kw-args] (fn-keywords [[:kw1 default kw1-supplied?]] kw-args {:method integer :req req :kw1 kw1 :kw1-supplied? kw1-supplied?})) (defmethod test2 java.lang.String [req kw-args] (fn-keywords [[:kw1 default]] kw-args {:method string :req req :kw1 kw1})) (defn test3 ([req1 kw-args] (fn-keywords [:kw1 :kw2] kw-args {:req1 req1 :kw1 kw1 :kw2 kw2})) ([req1 req2 kw-args] (fn-keywords [:kw1 :kw2] kw-args {:req1 req1 :req2 req2 :kw1 kw1 :kw2 kw2}))) (defn test4 [] (letfn [(inner [ kw-args] (fn-keywords [:kw1 :kw2] kw-args {:kw1 kw1 :kw2 kw2}))] (inner :kw1 hello :kw2 world))) Credit where it's due: I lifted ideas and bits of code from defnk. Thanks, Meikel! Comments welcome. -- Constantine Vetoshev -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: A macro for flexible keyword argument handling
Looks like Google Groups posting software forced line wraps at less than 80 columns, breaking the code. Lovely. Here's the fn-keywords macro reformatted for 72 column wrapping. (defmacro fn-keywords Adds flexible keyword handling to any form which has a parameter list: fn, defn, defmethod, letfn, and others. Keywords may be passed to the surrounding form as rest arguments, lists, or maps. Lists or maps must be used for functions with multiple arities if more than one arity has keyword parameters. Keywords are bound inside fn-keywords as symbols, with default values either specified in the keyword spec or nil. Keyword specs may consist of just the bare keyword, which defaults to nil, or may have the general form [:keyword-name keyword-default-value* keyword-bound?*]. keyword-bound? is an optional symbol bound to true if the keyword was supplied, and to false otherwise. [kw-spec-raw kw-args body] (let [kw-spec (map #(if (sequential? %) % [%]) kw-spec-raw) keywords (map first kw-spec) symbols (map (comp symbol name) keywords) defaults (map second kw-spec) destrmap {:keys (vec symbols) :or (apply hash-map (interleave symbols defaults))} supplied (reduce (fn [m [k v]] (assoc m k v)) (sorted-map) (remove (fn [[_ val]] (nil? val)) (partition 2 (interleave keywords (map (comp second rest) kw-spec) kw-args-map (gensym)] `(let [kw-args# ~kw-args ~kw-args-map (if (map? kw-args#) kw-args# (apply hash-map kw-args#)) ~destrmap ~kw-args-map] ~@(if (empty? supplied) body `((apply (fn [~@(vals supplied)] ~...@body) (map (fn [x#] (contains? ~kw-args-map x#)) [~@(keys supplied)]))) -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
ANN: Cupboard, an embedded database library for Clojure
I would like to announce the release of Cupboard, an embedded database library for Clojure. In a nutshell, it allows saving arbitrary struct maps to a database. It supports indices on struct keys, ACID transactions, and retrieval using non-trivial queries. For more details and sample code, please see its README file. http://github.com/gcv/cupboard The documentation is still fairly minimal, but, along with the provided examples, should be enough to get started. Cupboard is built on top of Berkeley DB JE (and includes a fairly complete Clojure wrapper for JE as a separate API), so some familiarity with Berkeley DB will help, but is not required. All comments and bug reports welcome. Thanks, Constantine Vetoshev --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Macros, namespaces, and lexical scope
On Sep 26, 7:35 am, Meikel Brandmeyer m...@kotka.de wrote: The problem is, that you quote the symbol you inject into the inner defmacro. Hence it does not get resolved. The solution in this case seems to be to syntax-quote the symbol correctly before injection. Replace the two ~'~ with ~~ and call the macro as (def-with-db-macro with-foo `open-foo `close-foo). This correctly resolves the symbols in the namespace calling def-with-db-macro and injects them into the with- foo expansion. I haven't really tested this, but it seems to be consistent with the macro machinery. Thank you. That works. I had tried ~~ by itself, and it didn't fly. I didn't think to syntax-quote the symbol in its place of expansion. So referring back to http://paste.lisp.org/display/87734, the solution is: user (defmacro make-myfoo [foo] `(defmacro ~'myfoo [s#] `(~~foo ~s#))) = #'user/make-myfoo user (ns tmp) tmp (user/make-myfoo `foo) = #'tmp/myfoo tmp (macroexpand '(tmp/myfoo bar)) = (tmp/foo bar) As expected, in the tmp namespace. This seems indeed useless at a first glance, but looking down the cause trace usually shows the real problem. Full stack trace follows, although I still don't know what it means. No message. [Thrown class java.lang.ExceptionInInitializerError] Backtrace: 0: sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 1: sun.reflect.NativeConstructorAccessorImpl.newInstance (NativeConstructorAccessorImpl.java:39) 2: sun.reflect.DelegatingConstructorAccessorImpl.newInstance (DelegatingConstructorAccessorImpl.java:27) 3: java.lang.reflect.Constructor.newInstance(Constructor.java:513) 4: java.lang.Class.newInstance0(Class.java:355) 5: java.lang.Class.newInstance(Class.java:308) 6: clojure.lang.Compiler$FnExpr.eval(Compiler.java:3428) 7: clojure.lang.Compiler.eval(Compiler.java:4531) 8: clojure.core$eval__3990.invoke(core.clj:1728) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Macros, namespaces, and lexical scope
(I asked these questions on #clojure, and the friendly locals suggested I open the question up for a wider audience.) I'm trying to write a macro-writing-macro. My code has a bunch of resources which have -open and -close type of calls, and they could all benefit from with- wrappers. The with- wrappers all have similar structure, and I thought I would be better off defining them with another macro: (defmacro def-with-db-macro [macro-name open-fn close-fn] `(defmacro ~macro-name [[var# open-args#] body#] `(let [~var# (apply ~'~open-fn [...@open-args#])] (try ~...@body# (finally (~'~close-fn ~var#)) Sample use: (def-with-db-macro with-db-env db-env-open db-env-close) (def-with-db-macro with-db db-open db-close) (def-with-db-macro with-db-txn db-txn-begin (fn [txn] (when (= @(txn :status) :open) (db-txn-commit txn This mostly works. It breaks if I try using, e.g., with-db-env in a namespace which does not import db-env-open or db-env-close. Chris Houser has summarized the problem here more succinctly than I can: http://paste.lisp.org/display/87734 While searching for a workaround, I thought maybe I could capture the functions I need during expansion of def-with-db-macro, but kept getting a useless exception. I ended up reducing that problem to this: (let [f1 #(inc %)] (defmacro m1 [x] `(~f1 ~x))) (m1 12) = No message. [Thrown class java.lang.ExceptionInInitializerError] The equivalent works in Common Lisp (Allegro CL and SBCL): (let ((f1 (lambda (y) (1+ y (defmacro m1 (x) `(funcall ,f1 ,x))) (m1 12) = 13 Thoughts on either of these brain teasers? Thanks! PS: To read the IRC discussion, see http://clojure-log.n01se.net/date/2009-09-25.html and scroll down to the discussion starting at 15:16. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Macros, namespaces, and lexical scope
On Sep 25, 6:02 pm, John Harrop jharrop...@gmail.com wrote: I don't think you can use things like defmacro in a let. This works: (let [y 10] (defmacro m1 [] `(list ~y))) (m1) = (10) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Schema for data structures
On Sep 24, 10:59 am, Miron Brezuleanu mbr...@gmail.com wrote: Well, I only want to enforce duck-typing :-) - for instance, make sure via unit tests that a function that should return a data structure with certain properties always returns such a data structure. Not exactly what you asked for, but I added a defstruct* helper to my utils.clj. I'm still not entirely sure it's a good idea, but here it is: (defmacro defstruct* Wrapper for defstruct which also creates a simple duck type checking function. [name slots] `(do (defstruct ~name ~...@slots) (defn ~(symbol (str is- name ?)) [x#] (if (map? x#) (let [sample# (struct ~name)] (empty? (clojure.set/difference (set (keys sample#)) (set (keys x#) false Use it just like you use defstruct, e.g.: (defstruct* person :first- name :last-name :age), but it will also create a little type-checker function: is-person? Here are some tests to see how it works: (defstruct* duck-typed-struct :a :b :c) (deftest duck-typed-predicates (let [dt1 (struct duck-typed-struct 1 2 3) dt2 {:a 4 :b 5 :c 6} dt3 (struct duck-typed-struct 1 2) dt4 {:a 4 :b 5 :c nil} not-dt1 {:a 4 :b 5} not-dt2 {:d 7 :e 8} not-dt3 {:a 4 :b 5 :d 7}] (is (is-duck-typed-struct? dt1)) (is (is-duck-typed-struct? dt2)) (is (is-duck-typed-struct? dt3)) (is (is-duck-typed-struct? dt4)) (is (not (is-duck-typed-struct? not-dt1))) (is (not (is-duck-typed-struct? not-dt2))) (is (not (is-duck-typed-struct? not-dt3) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Redefining Special Forms
On Sep 17, 2:55 pm, Chouser chou...@gmail.com wrote: In a new thread, vars always start with their root binding. There's an ongoing discussion about the best way to provide other options when this is not the desired behavior: http://www.assembla.com/spaces/clojure/tickets/170-bound-fn-macro That discussion implies that code on a different thread has to explicitly ask for other threads' bindings. Is there a way to provide some kind of inherited-binding macro, which works just like binding but allows all threads started within its scope to automatically have access to variables it has bound? As icing on the cake, I'd like to allow binding and inherited-binding to create new variables with dynamic extent. Right now, binding always has to rebind previously def'ed or declare'd variables. This change would allow applying the power of dynamic variables in a more targeted manner, and make them less like glorified globals. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Correct idiom for looping inside a catch or finally form?
I have some code which opens a bunch of resources (say, files), and needs to make sure they all get closed. Something like this: (let [files (atom [])] (try (open-my-many-files files) ;; the files atom now refers to a vector of open file handles (do-dangerous-io @files) (finally (doseq [file @files] (.close file) The Clojure compiler does not like this: error: java.lang.UnsupportedOperationException: Cannot recur from catch/finally Does Clojure have a lower-level iteration primitive than loop and recur, which I can use inside exception handling code? I can obviously put a letfn inside the finally and use good old recursion, but I feel uncomfortable doing this without TCO. (Yes, I know I'm likely to run out of file descriptors before I run out of available stack frames, but this is still the wrong way to do things.) I would also very much prefer not to have to write and call out to Java helper classes for something as trivial as a loop. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Correct idiom for looping inside a catch or finally form?
Apparently I oversimplified my example. In reality, I am trying to deal with a bunch of open Berkeley DB cursors which I need to combine. They cannot be processed serially. I need to ensure that all those cursors close at the end even if an exception occurs, so I need to loop over the resulting list or vector of open cursor handles. This list happens to be stored in an atom, but that is completely irrelevant to the problem I am trying to resolve: Clojure does not seem to support iteration inside catch or finally forms. Thanks, CV On Sep 13, 5:09 pm, Kevin Downey redc...@gmail.com wrote: you are using an atom as a temporary variable. please don't do that. (doseq [f files] (with-open [of (open-file f)] (do-dangerous-io of))) On Sun, Sep 13, 2009 at 1:05 PM, Constantine Vetoshev gepar...@gmail.com wrote: I have some code which opens a bunch of resources (say, files), and needs to make sure they all get closed. Something like this: (let [files (atom [])] (try (open-my-many-files files) ;; the files atom now refers to a vector of open file handles (do-dangerous-io @files) (finally (doseq [file @files] (.close file) The Clojure compiler does not like this: error: java.lang.UnsupportedOperationException: Cannot recur from catch/finally Does Clojure have a lower-level iteration primitive than loop and recur, which I can use inside exception handling code? I can obviously put a letfn inside the finally and use good old recursion, but I feel uncomfortable doing this without TCO. (Yes, I know I'm likely to run out of file descriptors before I run out of available stack frames, but this is still the wrong way to do things.) I would also very much prefer not to have to write and call out to Java helper classes for something as trivial as a loop. -- And what is good, Phaedrus, And what is not good— Need we ask anyone to tell us these things? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Re: Correct idiom for looping inside a catch or finally form?
On Sep 13, 11:18 pm, Richard Newman holyg...@gmail.com wrote: I think the OP's issue was that he has a sequence of things to close, determined at runtime. with-open itself is no use there, because the things to close must be known at compile-time. Exactly. He is correct that finally and catch do not permit iteration. They do permit function calls, hence my workaround. Thank you, Richard. Your suggestion works. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---
Inheriting Clojure special variables in child threads
Clojure's binding form only establishes vars with dynamic extent limited to the current thread. This makes a lot of sense. However, I have a use case where I'd like it to establish the dynamic extent in a way which affects the current thread and all threads started within the current thread. Suppose, for example, that I want to launch a couple of different instances of the embedded Jetty server. I have no control over what threads Jetty starts and stops, but I want to make sure that my code running inside that entire instance has a specific global variable binding: (declare *x*) (binding* [*x* 3] (start-jetty :port 8001 :my-servlet servlet-implemented-in-clojure)) (binding* [*x* 5] (start-jetty :port 8002 :my-servlet servlet-implemented-in-clojure)) That way, code I wrote to run inside of Jetty can blindly refer to *x*, and the first instance would then use the value 3, and the second instance would use the value 5. Basically, I'd like a binding* macro to establish a dynamic binding visible only in thread hierarchies started in its scope. Aside from the utility in my use case, I think a binding* macro like this would improve the current concurrency situation, where any thread can alter a def'ed global variable for any other thread. If the thread starts in a binding*, it would, at worst, affect itself and its children. Seems useful. Any comments? Is this possible? How difficult would this be to implement? Best regards, Constantine Vetoshev --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~--~~~~--~~--~--~---