Printing and reading a function

2009-06-25 Thread Jurjen

I've been trying to do some generic work on serializing clojure
objects, and am much impressed with how easy and functional it is, as
well as how easy it is to extend this to other objects (eg Java
classes).

However, I seem to come a little unstuck when it comes to functions /
closures. I realise capturing the state of the environment is going to
be tricky at best, but at the moment I'm trying to extend the basic
defn macro to capture the code used to define the function.
I then tried using print-dup to print the source string from the meta
data, but this is where things stop working.

As far as I can see from the clojure/core-print.clj file, doing a
(binding [*print-dup* true] (pr-str function)) should print out the
meta-data of the function as well, but this does not seem to be
happening. I want this to happen, as I need access to the metadata to
dump the code used instead of the default #=(user
$eval__17$function__19. ) string.

Essentially my new version of defn is a basic wrapper around defn:
(defmacro mkfn [nm args func]
  (list 'defn nm {:source (str "(mkfn " nm " " args " " func ")")}
args func))

so when you do (mkfn test1 [a b] (+ a b)) you get out a function test1
with a metadata :source tag (meta (var test1))
{:ns #, :name test1, :file "NO_SOURCE_PATH", :line
439, :arglists ([a b]), :tag "sometag", :source "(mkfn test1 [a b] (+
a b))"}

I tried to override the print-dup for clojure.lang.Fn to check for
the :source meta-data tag, but I keep getting NullPointerExceptions.
Anyone got any ideas? Am I missing something obvious?

(defmethod print-dup clojure.lang.Fn [o w]
  (if (meta o) (.write w (:source (meta o)))
(print-ctor o (fn [o w]) w)))


--~--~-~--~~~---~--~~
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: Save current namespace like a Smalltalk image

2009-07-08 Thread Jurjen

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



Re: Save current namespace like a Smalltalk image

2009-07-08 Thread Jurjen

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 #) 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  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 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