evaluating s-expressions from Java

87 views
Skip to first unread message

.Bill Smith

unread,
Nov 29, 2007, 9:44:08 AM11/29/07
to Clojure
Has anyone considered how to pass s-expressions to Clojure from Java?
I know Clojure is implemented in Java, but that's what I mean.
Rather, starting from a Java program whose purpose is not necessarily
to process Lisp, I want now and then to evaluate an s-expression --
perhaps just for its side-effects.

-Bill

Rich Hickey

unread,
Nov 29, 2007, 11:30:34 AM11/29/07
to Clojure
Yes, this (embedding) is definitely a fully supported objective of
Clojure, currently woefully under-documented, but deep in the design.

I want Java programs to be able to create and consume Clojure data
structures, call upon Clojure to do evaluation etc, at a much richer
level than 'please evaluate this text'.

The biggest hitch right now is a lack of documentation of the runtime
library. This is due to time constraints and the fact that I am still
doing some refactoring/renaming in there. But the core is quite sound,
I use the Clojure data structures all the time in my Java programs,
treating clojure.jar as a library.

The caveat is that some of the names/locations might change.
Eventually there will be JavaDoc on what one can safely use and how.

To start, there is Compiler.eval(), which takes a form (data
structure, not text), evaluates it and returns the result. If you've
got text to evaluate, you can use LispReader.read() to get data, or
use Compiler.load() from a stream. You can create any of the
Persistent* collections (use the static create() functions or the
static EMPTY objects, and manipulate them via the IPersistent*
interfaces. You can create Symbol/Keywords with their respective
intern()s. Look to the RT class for first(), rest(), seq(), conj(),
assoc() etc helpers. You can even implement functions in Java for
Clojure's use by deriving from IFn (or the helper classes AFn/RestFn).
The Num class is the entry point for numeric stuff. Etc.

Going the other way, if you get back a Clojure collection, it
implements Collection, Iterable etc. All the numerics implement
Number. If you get back from Clojure a function object, it is already
compiled, and can be called using the IFn interface invoke() methods.
This is much faster than repeatedly calling eval with a call form.
Clojure functions also implement Callable.

Look at Repl.java for a small program that hosts Clojure, because
that's what it is.

I hate it when the only interface to an embedded language is through
strings/text. Clojure offers much more. Hopefully soon I'll get time
to doc it all...

Henk Boom

unread,
Dec 6, 2007, 10:41:12 PM12/6/07
to clo...@googlegroups.com
On 29/11/2007, Rich Hickey <richh...@gmail.com> wrote:
> To start, there is Compiler.eval(), which takes a form (data
> structure, not text), evaluates it and returns the result. If you've
> got text to evaluate, you can use LispReader.read() to get data, or
> use Compiler.load() from a stream.

Compiler.load seems to always return :t, not the value the given
program returns. Is this really what is desired?

Henk

Rich Hickey

unread,
Dec 7, 2007, 8:26:15 AM12/7/07
to Clojure


On Dec 6, 10:41 pm, "Henk Boom" <lunarcri...@gmail.com> wrote:
Well, programs aren't really a concept in Clojure, but it does seem
more useful to return the value of the last expression. I changed it
(and loadFile) to do that. Any problems will throw an exception. I
will eventually add a flag to load-file to enable a file-does-not-
exist return value.

Rich
Reply all
Reply to author
Forward
0 new messages