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
-~----------~----~----~----~------~----~------~--~---

Reply via email to