Ok, so code is data...

424 views
Skip to first unread message

Bill Robertson

unread,
May 9, 2011, 11:36:45 PM5/9/11
to Clojure
How do I actually manipulate it? I have some complicated logic that I
would like to transform into html (or maybe xml) for display
purposes.

I'm generating the Clojure code by parsing some nasty Java and
outputting s-expressions. The Java is basic, but quite deeply
nested. I want to generate working Clojure to demonstrate what that
can do for us, and get this nastiness documented of course.

Other than going into the source files and transforming it by hand
into a series of defs and quoted lists e.g. (def my_func '(+ 1 2))
How do I actually just load code w/o evaluating it?

I've found the pretty printer macros, seems like that might be useful
if I wanted to statically transform the code. I found the walker,
that looks like it might be useful in actually generating the output
(e.g. visit things, spit out (x|ht)ml.

I looked at the various load functions in clojure.core. With the
exception of load (http://clojure.github.com/clojure/clojure.core-
api.html#clojure.core/load) they all seem to load and evaluate. Is
load the answer or is it something I haven't found yet?

Once I get the code loaded, I don't think I need anything out of the
ordinary like macros or multi-methods. I think I can just manipulate
the lists. Does that sound correct?

I'm sorry if this are a stupid questions, but I've never done anything
in Clojure of any significance, and any helpful answers you provide
would could save me days of stumbling about.

Thanks!


Justin Kramer

unread,
May 10, 2011, 1:32:08 AM5/10/11
to Clojure
'read' and 'read-string' are what you're looking for. They each read a
single Clojure object from an input source (PushbackReader for read,
String for read-string).

Alternatively, something like this can read all top-level forms from a
file:

(defn read-all
"Reads all top-level forms from f, which will be coerced by
clojure.java.io/reader into a suitable input source. Not lazy."
[f]
(with-open [pbr (java.io.PushbackReader. (clojure.java.io/reader
f))]
(doall
(take-while
#(not= ::eof %)
(repeatedly #(read pbr false ::eof))))))

(read-all "/some/clojure/file.clj")
=> ((foo :bar) (baz))

Justin

Bill Robertson

unread,
May 10, 2011, 6:55:26 AM5/10/11
to Clojure
Thank you very much.

Stefan Kamphausen

unread,
May 10, 2011, 8:06:41 AM5/10/11
to clo...@googlegroups.com
Hi,

from what you write I get the feeling, that you may be doing things in a too complicated manner.  Maybe I am wrong.

In any case, although it may not be Clojure but Common Lisp, you might want to take a look at the HTML generation in Peter Seibels excellent Practical Common Lisp: See chapter 30 and 31 in http://gigamonkeys.com/book/

After reading that, diving into Enlive may be easier to understand.  See https://github.com/cgrand/enlive

But then again, as I said, maybe I just misunderstood what you really want.


Kind regards,
Stefan

Jonathan Fischer Friberg

unread,
May 10, 2011, 11:26:43 AM5/10/11
to clo...@googlegroups.com
"How do I actually just load code w/o evaluating it?"
mostly when you want something like this, you want a macro. Manipulating code is also done within macros.

http://www.gigamonkeys.com/book/macros-standard-control-constructs.html
http://www.gigamonkeys.com/book/macros-defining-your-own.html

Jonathan

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Timothy Baldridge

unread,
May 10, 2011, 11:37:30 AM5/10/11
to clo...@googlegroups.com

On Tue, May 10, 2011 at 10:26 AM, Jonathan Fischer Friberg <odys...@gmail.com> wrote:
"How do I actually just load code w/o evaluating it?"
mostly when you want something like this, you want a macro. Manipulating code is also done within macros.
 

Yeah, I would consider the whole code-is-data thing to refer more to using macros than eval. For something fun to read up on this check out this tutorial:

http://www.learningclojure.com/2010/09/clojure-faster-than-machine-code.html

Here the author goes and takes a tree data structure, and on-the-fly generates function that represents that structure. The result is some insanely fast code.

Timothy

Bill Robertson

unread,
May 10, 2011, 11:18:03 PM5/10/11
to Clojure
Thanks for the feedback and pointers.



On May 10, 11:37 am, Timothy Baldridge <tbaldri...@gmail.com> wrote:
> On Tue, May 10, 2011 at 10:26 AM, Jonathan Fischer Friberg <
>
> odysso...@gmail.com> wrote:
> > "How do I actually just load code w/o evaluating it?"
> > mostly when you want something like this, you want a macro. Manipulating
> > code is also done within macros.
>
> Yeah, I would consider the whole code-is-data thing to refer more to using
> macros than eval. For something fun to read up on this check out this
> tutorial:
>
> http://www.learningclojure.com/2010/09/clojure-faster-than-machine-co...

Kovas Palunas

unread,
Nov 29, 2021, 3:16:23 PM11/29/21
to Clojure
Just stumbled across this thread 10 years later!  I'm actually interested in doing the same thing: taking some clojure logic that I write and converting it to a call-graph in html. Is there any prior art here I should know about?  Or can this be done with basic clojure to e.g. convert the code of a function into nested lists for me to then convert to html?

 - Kovas

Brent Millare

unread,
Nov 30, 2021, 9:58:50 AM11/30/21
to Clojure
Do you want to create an html visualization in html? The main thing to check is other code walkers for reference like https://github.com/ztellman/riddley but I strongly recommend trying this out yourself without using other libraries as you will learn a lot in the process.

You don't need to "convert" clojure to nested lists. It already is a nested list. Wrapping a clojure exp in a macro provides the macro with the unevaluated nested data. Alternatively, when viewing files, then you simply want to call read/read-string on raw clj file data.

Reply all
Reply to author
Forward
0 new messages