I seem to be lagging a little in the conversation, but for what it's worth, the code I use to capture function definitions is:
(defmacro mkfn "Create a function and record the source in the var metadata" [name & fdecl] (list* `defn (with-meta name (assoc (meta name) :source (str (list* `mkfn name fdecl)))) fdecl)) which is based on the macro [defn-] (from clojure.core) so will work exactly as [defn] does. To get the source back, you need to access the metadata of the var that points to the function, so for (mkfn test [a b] (+ a b)) you would use (meta (var test)). I also thought about keeping previous definitions (like version control) because I tend to occasionally destroy perfectly fine functions. This could be done by changing the assoc line to keep a list of definitions, but tends to cause a bit of clutter... I can then dump any namespace to a string (to write to a file / post to net / etc) (mkfn get-ns "Prints the public contents of the given namespace" [ns] (map #(if (:source (meta (second %1))) ; check if source was recorded (:source (meta (second %1))) (if (:macro (meta (second %1))) '() ; macros not handled yet... (list 'def (binding [*print-dup* true] ; else use generic print- dup (pr-str (second %1)) (pr-str (first %1))) (eval (first %1))))) (ns-publics ns))) ; over all public vars in ns This still has some issues, especially if you have defined some unbound vars, so is still very much a work-in-progress. As you might note, macros aren't handled yet as print-dup tends to throw exceptions on them when it encounters (eval (first %1)). Also note that any functions defined by [defn] will be printed as (defn func #<user$func__134 user$func__...@1570c24>) so when reading back in, the reader will choke on the #<...> form (CompilerException java.lang.RuntimeException: java.lang.Exception: Unreadable form) Hope its useful for you, your mileage may vary (greatly, I expect) If I get it down to something useful and reasonably functional, I'll submit it to clojure.contrib, but for now that's about all I use. Jurjen On Jul 8, 11:46 pm, Robert Campbell <rrc...@gmail.com> wrote: > Hi Jurjen, > > That wrapper for defn is something I was looking for in another post; > I previously asked how I can inspect the definitions of my functions > on the REPL. When I'm exploring stuff I'll be redefining many > functions many times and sometimes I lose track things. I basically > have to scroll around searching my REPL for the last definition. It > sounds like you have a solution to this problem. It seems strange to > me that Clojure doesn't support this concept natively. At some point > the function definition is compiled into bytecode to run on the JVM, > why not just automatically safe the original definition in metadata > when this is done? Have you should about adding your wrapper code to > Contrib? > > Rob > > > > On Wed, Jul 8, 2009 at 12:30 PM, Jurjen<jurjen.hait...@gmail.com> wrote: > > > I had the same thought (as posted in the other thread) and haven't > > come to a final solution yet. The main reason I wanted to achieve it > > was that I do my developing / tinkering / brainstorming spread over > > several work boxes spread out through several locations, and a clojure > > REPL is cheap and easy, whereas maintaining several IDEs in synch (3 > > locations at work, 2 at home) can be a bit of a nightmare. > > > The compromise I've got at the moment is that I've made a custom > > wrapper around [defn] that records the code used to create the > > instance, and stores it in the metadata of the var that points to the > > function. I can then cycle through the namespace definitions using ns- > > interns / ns-publics and see the definition of each function, and can > > save it to a file. > > > I tried to create a print-dup method so that the entire contents of a > > namespace could be dumped to a file, but as chouser pointed out, print- > > dup works on the function itself, whereas the code is stored in the > > metadata of the var that points to the function (and there's no back- > > link from the function to the var), so now it is a multi-stage process > > to port current code in its entirety, but as I'm generally only > > working on fairly limited areas of code it isn't a huge deal. > > Also, any closures are not captured by capturing the source, so > > there's still issues there, but for me the function definition is > > generally good enough. Still have to implement it for macros as well, > > but haven't needed that as much. > > > Incidentally, I find the easiest way to port my code around is to > > print it to the repl, then cut-and-paste it to etherpad, which I can > > then access from anywhere (without having to save). Now if only there > > was a hosted REPL that integrated an IDE nicely I would really be set. > > Lord-of-all-repls comes close, but is not pure clojure or JVM. > > > Jurjen > > > On Jul 8, 8:13 pm, Robert Campbell <rrc...@gmail.com> wrote: > >> Hello, > > >> Sometimes I have pretty long REPL sessions where I'm trying to flesh > >> out some ideas. When I close my instance of Clojure Box (Emacs based) > >> I lose all the definitions I had worked out over time. Is there any > >> way to dump namespace(s) to an image? It would be great to be able to > >> load up some workspace image and pick up where I left off. > > >> Rob --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---