Choosing a Scripting Language for a Java Application

9 views
Skip to first unread message

Randall R Schulz

unread,
Apr 29, 2008, 5:07:16 PM4/29/08
to jvm-la...@googlegroups.com
Hi,

I don't know if this question is appropriate, so if not, please ignore
it and accept my apologies for being off-topic.


I am setting out to add scriptability to a largish and relatively
mature, though still evolving, Java application. The application is a
theorem prover and it operates on formulas expressed in the CLIF
notation, about which it's enough to know that it's syntactically a
Lisp-like language.

Because of this I'd like to use a Lisp dialect to add scripting. Right
now, I'm looking mostly at SISC and Kawa.

So my question is this: What sort of analysis should I be making to
select between these two?

One thing I'll point out is that there will be quite a lot of
interaction across the boundary between the scripting language and the
existing Java application. I.e., there will be a lot of functions or
methods that can be invoked on the scripting side to gather information
about and manipulate the content being operated on and to initiate
problem execution on the Java side.

I mention this because if it's tedious to make any given bit of
Java-side functionality accessible to the scripting side, that will be
a negative.


Lastly, if there are other Lisp-like scripting languages that integrate
well with Java, I'd like to hear about them, too. My research suggests
that while many such projects have been created, not many are actively
developed or are very complete implementations of Lisp (or Scheme).


Thanks.


Randall Schulz

Jochen Theodorou

unread,
Apr 29, 2008, 5:22:58 PM4/29/08
to jvm-la...@googlegroups.com
Randall R Schulz schrieb:

> Hi,
>
> I don't know if this question is appropriate, so if not, please ignore
> it and accept my apologies for being off-topic.
>
>
> I am setting out to add scriptability to a largish and relatively
> mature, though still evolving, Java application. The application is a
> theorem prover and it operates on formulas expressed in the CLIF
> notation, about which it's enough to know that it's syntactically a
> Lisp-like language.
>
> Because of this I'd like to use a Lisp dialect to add scripting. Right
> now, I'm looking mostly at SISC and Kawa.

Lisp-like language in the sense of having lots of ( and ), or do you
also have macros?

> So my question is this: What sort of analysis should I be making to
> select between these two?
>
> One thing I'll point out is that there will be quite a lot of
> interaction across the boundary between the scripting language and the
> existing Java application. I.e., there will be a lot of functions or
> methods that can be invoked on the scripting side to gather information
> about and manipulate the content being operated on and to initiate
> problem execution on the Java side.
>
> I mention this because if it's tedious to make any given bit of
> Java-side functionality accessible to the scripting side, that will be
> a negative.

maybe you should simply give both a try and take what felt to be the
best. Maybe asking for help on the mailing list of these languages would
help too, especially if you describe your language and what you need. I
am sure they can tell you where a possible problem hides.

> Lastly, if there are other Lisp-like scripting languages that integrate
> well with Java, I'd like to hear about them, too. My research suggests
> that while many such projects have been created, not many are actively
> developed or are very complete implementations of Lisp (or Scheme).

how complete does it have to be?

bye blackdrag

--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/

Randall R Schulz

unread,
Apr 29, 2008, 5:41:35 PM4/29/08
to jvm-la...@googlegroups.com
On Tuesday 29 April 2008 14:22, Jochen Theodorou wrote:
> Randall R Schulz schrieb:
> > Hi,
> >
> > I don't know if this question is appropriate, so if not, please
> > ignore it and accept my apologies for being off-topic.
> >
> >
> > I am setting out to add scriptability to a largish and relatively
> > mature, though still evolving, Java application. The application is
> > a theorem prover and it operates on formulas expressed in the CLIF
> > notation, about which it's enough to know that it's syntactically a
> > Lisp-like language.
> >
> > Because of this I'd like to use a Lisp dialect to add scripting.
> > Right now, I'm looking mostly at SISC and Kawa.
>
> Lisp-like language in the sense of having lots of ( and ), or do you
> also have macros?

CLIF is to Lisp as Java is to C++. That is, if you blur your eyes, you
can't tell them apart. Otherwise they have nothing in common.
(Actually, Java has a lot more in common with C++ than CLIF does with
Lisp.)

One reason I'm looking to Lisp or Scheme as the scripting language is
that I don't want a lot of disparate syntaxes in my system. The other
is that I'm fond of Lisp as a language.

[ As an aside, my application supports user-definable search heuristics.
They are specified in a Lisp-y manner, too, even though that's done
with a separate Lisp reader and data structure library and a
purpose-built compiler and evaluator. Unfortunately, the Lisp reader
library has no evaluator, it just reads and write (Common) Lisp lists
and atoms, so it's not an option as far as my scripting needs go. But
the nice part is that users don't know that. They just see lots of
S-Expressions. ]


> > So my question is this: What sort of analysis should I be making to
> > select between these two?
> >

> > ...


>
> maybe you should simply give both a try and take what felt to be the
> best. Maybe asking for help on the mailing list of these languages
> would help too, especially if you describe your language and what you
> need. I am sure they can tell you where a possible problem hides.

Well, we're a very small operation with more to do than we can really
accomplish, so I don't have the luxury of running competitive
implementations. I have to do my best to choose correctly up front.


> > Lastly, if there are other Lisp-like scripting languages that
> > integrate well with Java, I'd like to hear about them, too. My
> > research suggests that while many such projects have been created,
> > not many are actively developed or are very complete
> > implementations of Lisp (or Scheme).
>
> how complete does it have to be?

I'm inclined to say not very, but I have a niggling feeling that it
would be a mistake to choose something that is only a toy fragment of a
real language. SISC and Kawa both purport to be complete or
near-complete R5RS implementations, and while that's not a first-order
requirement, it is nice and I think it could turn out to be
serendipitous to have a full implementation. (Is it contradictory or
oxymoronic to antipicate serendipity?)


> bye blackdrag


Randall Schulz

David Huebel

unread,
Apr 29, 2008, 5:42:22 PM4/29/08
to jvm-la...@googlegroups.com
On Tue, Apr 29, 2008 at 4:07 PM, Randall R Schulz <rsc...@sonic.net> wrote:
> I am setting out to add scriptability to a largish and relatively
> mature, though still evolving, Java application.
...

> So my question is this: What sort of analysis should I be making
> to select between these two?

Be sure to consider issues of deployment -- will you need to load
source files out of jars or as classloader resources? Does the
application use classloaders in interesting ways that might trip up
the language implementation? Do you need to create multiple
independent language runtimes, and if so, does the language
implementation support that? Some of these features, if missing,
might be easy for you to add -- ask a developer. And (of course) ask
programmers on the language's user mailing list to share their
experiences.

-David

Randall R Schulz

unread,
Apr 29, 2008, 6:08:52 PM4/29/08
to jvm-la...@googlegroups.com
On Tuesday 29 April 2008 14:42, David Huebel wrote:
> On Tue, Apr 29, 2008 at 4:07 PM, Randall R Schulz <rsc...@sonic.net>
wrote:
> > I am setting out to add scriptability to a largish and relatively
> > mature, though still evolving, Java application.
>
> ...
>
> > So my question is this: What sort of analysis should I be making
> > to select between these two?

Thanks for the feedback. Though I know you don't need or want to know
these things, I'll outline the answers in case it leads to any
secondary concerns:


> Be sure to consider issues of deployment -- will you need to load
> source files out of jars or as classloader resources?

I will probably want to bundle some scripts (in the JAR file or files)
and certainly will need to allow others to be supplied from outside the
the application proper. (More or less—in many cases scripts would come
from the content repository which in one of the two key deployment
modes is a Grails application and they whole business is bundled
together and deployed into a servlet container.)


> Does the application use classloaders in interesting ways that might
> trip up the language implementation?

My application does not, but the fact that its deployed in a servlet
container might make the answer a de facto "yes." I'm not sure.


> Do you need to create multiple independent language runtimes, and if
> so, does the language implementation support that?

I believe the answer is yes, since the Web app deployment mode is
multi-threaded with multiple concurrent users, in general.


> Some of these features, if missing, might be easy for you to add --
> ask a developer. And (of course) ask programmers on the language's
> user mailing list to share their experiences.


> -David


Thanks again.


Randall Schulz

Per Bothner

unread,
Apr 29, 2008, 7:33:30 PM4/29/08
to jvm-la...@googlegroups.com, Randall R Schulz
Randall R Schulz wrote:
> Because of this I'd like to use a Lisp dialect to add scripting. Right
> now, I'm looking mostly at SISC and Kawa.
>
> So my question is this: What sort of analysis should I be making to
> select between these two?
>
> One thing I'll point out is that there will be quite a lot of
> interaction across the boundary between the scripting language and the
> existing Java application. I.e., there will be a lot of functions or
> methods that can be invoked on the scripting side to gather information
> about and manipulate the content being operated on and to initiate
> problem execution on the Java side.
>
> I mention this because if it's tedious to make any given bit of
> Java-side functionality accessible to the scripting side, that will be
> a negative.

Kawa provides very easy access to almost all of Java, and because Kawa
is compiler-based, there is little or no impedance mismatch between
your code and Kawa: You can easily call a Java method, access a Java
array, set a Java field, invoke a synchronized section, catch or throw
an exception, etc, etc. And doing so compiles into the similar bytecode
that javac generates, so there is no need to use reflection or
emulation. There is never (well, hardly ever) a need to "escape into
Java" for performance reasons or because you can't access a feature
from Kawa. (An example of one of the rare exception is annotations -
Kawa doesn't yet provide a mechanism to annotation a declaration.
It's on my to-do list ...)

Kawa also provides deployment flexibility: You can use eval, a repl,
compile your "script" into class files, compile a file on-the-fly,
create a servlet, etc. And Kawa takes care with line numbers and
other debug information, so you get useful exception stack traces.
--
--Per Bothner
p...@bothner.com http://per.bothner.com/

Randall R Schulz

unread,
Apr 29, 2008, 7:44:21 PM4/29/08
to jvm-la...@googlegroups.com
On Tuesday 29 April 2008 16:33, Per Bothner wrote:
> ...

>
> Kawa provides very easy access to almost all of Java, and because
> Kawa is compiler-based, there is little or no impedance mismatch
> between your code and Kawa: ...

>
> Kawa also provides deployment flexibility: You can use eval, a repl,
> compile your "script" into class files, compile a file on-the-fly,
> create a servlet, etc. ...

Thanks, Per. That's all very useful information.

I've done a little experimentation with SISC (mostly on a tangential
aspect), but I'll look into Kawa.


By the way, does Kawa rhyme with Java??


Randall Schulz

Per Bothner

unread,
Apr 29, 2008, 7:53:41 PM4/29/08
to jvm-la...@googlegroups.com
Randall R Schulz wrote:
> By the way, does Kawa rhyme with Java??

Most of the time I pronounce it that way ... But "Kawa" is based on
the Polish word for coffee, and IIRC the "w" is closer to the English
"w" than the English "v". The original Kawa 0.1 was an interpreter
started by Alex Milowski, who is of Polish heritage. I took over Kawa
early on (with Alex's blessing), implemented a compiler, and over the
years have essentially re-written it a couple of times over ...

Rich Hickey

unread,
Apr 29, 2008, 8:15:46 PM4/29/08
to JVM Languages
Hi Randall,

I recommend you also take a look at Clojure. While not Scheme or
Common Lisp, it is functionally rich, and has a number of advantages
over a 'standard' Lisp in the Java environment, particularly as
regards interoperability:

It shares the Java type system. For instance Clojure strings are Java
strings (that can't be true of any standard Lisp where strings are
mutable). Clojure collections implement java.util.Collection.

Clojure has a large sequence library (first/rest/map/filter/reduce/
take/drop etc) that is defined on an abstraction rather than cons
cells, and as such works on all Clojure data structures as well as
Java strings, Java arrays, and any Java Iterable collection or
Enumerator.

Clojure uses Java's calling conventions and call stack. Clojure
closures (fns) implement Callable, Runnable and Comparator.

All Clojure data types are represented by a well-factored set of Java
interfaces that are easy to consume from Java.

Clojure compiles to JVM bytecode and has excellent performance. It
supports optional type hints and simple inference that allow it to
avoid reflection. Clojure supports standard Java debug information.

Clojure's math library works directly with Java's boxed Number types,
including BigInteger and BigDecimal, adding only a Ratio type of its
own.

Clojure has a clean and intuitive Java call interface:

user=> (def s "foobar")
#'user/s

user=> (s.replace "o" "e")
"feebar"

The net result is much more of an integrated feel than one language
bridging to another.

You can find out more at:

http://clojure.org

Regards,

Rich

Randall R Schulz

unread,
Apr 29, 2008, 8:25:32 PM4/29/08
to jvm-la...@googlegroups.com
On Tuesday 29 April 2008 17:15, Rich Hickey wrote:
> On Apr 29, 5:07 pm, Randall R Schulz <rsch...@sonic.net> wrote:
> > ...

> >
> > Lastly, if there are other Lisp-like scripting languages that
> > integrate well with Java, I'd like to hear about them, too. My
> > research suggests that while many such projects have been created,
> > not many are actively developed or are very complete
> > implementations of Lisp (or Scheme).
>
> Hi Randall,
>
> I recommend you also take a look at Clojure. While not Scheme or
> Common Lisp, it is functionally rich, and has a number of advantages
> over a 'standard' Lisp in the Java environment, particularly as
> regards interoperability:

Oh, great. Another system I have to look at...

Seriously, thanks for the information. I've heard of Clojure, but know
nothing about it (beyond what you've written). I'll definitely check it
out. At least I know how to pronounce it (I think).


> ...
>
> Rich


Randall Schulz

Randall R Schulz

unread,
Apr 29, 2008, 8:44:11 PM4/29/08
to jvm-la...@googlegroups.com
On Tuesday 29 April 2008 17:15, Rich Hickey wrote:
> ...
>
> Hi Randall,
>
> I recommend you also take a look at Clojure. ...

You might want to get Clojure listed here:

<http://www.robert-tolksdorf.de/vmlanguages.html>


RRS

Per Bothner

unread,
Apr 29, 2008, 8:45:33 PM4/29/08
to jvm-la...@googlegroups.com
Rich Hickey wrote:

[Hope you'll forgive me making this an excuse for a competitive
comparison ...]

> [Clojure] shares the Java type system. For instance Clojure strings are Java


> strings (that can't be true of any standard Lisp where strings are
> mutable).

Kawa has both constant strings (java.lang.String) and
mutable strings (gnu.lists.FString). Both implement
java.lang.CharSequence. If you specify that a variable
is a <string> (Kawa has optional type declarations),
it uses the type java.lang.CharSequence.

This gives us the best of both worlds: Java *and* Scheme
interoperability.

> Clojure collections implement java.util.Collection.

Kawa lists, vectors, mutable strings, etc all implement java.util.List.

> Clojure uses Java's calling conventions and call stack.

Kawa by default does the same. Kawa has an option to use a calling
convention that supports full tailcalls (and has some other advantages).
Of course a procedure compiled with one calling convention can
automatically an procedure compiled with the other calling convention,
or an unknown procedure compiled with an unknown calling convention.

> Clojure compiles to JVM bytecode and has excellent performance. It
> supports optional type hints and simple inference that allow it to
> avoid reflection. Clojure supports standard Java debug information.

Kawa has done all of this for a decade ...

> Clojure's math library works directly with Java's boxed Number types,
> including BigInteger and BigDecimal, adding only a Ratio type of its
> own.

Kawa does use its own bignum implementation gnu.math.IntNum - partly
because it precedes java.lang.BigInteger! I continue using IntNum
partly because it is more efficient that BigInteger - it especially
wins when most integers are "small" as is almost always the case.
Another reason for gnu.math.* is that actually implements the
Scheme numeric tower - but extended to support quantities.
For example, Kawa has length (3cm) and time (2.5s) literals,
which are useful for GUIs etc.

Of course Kawa can also convert to and from the standard
subclasses of java.lang.Number and (mostly) supports "mixed-mode"
arithmetic between the standard number and java.math classes
and the gnu.math.* classes (which extend java.lang.Number).

> Clojure has a clean and intuitive Java call interface:
>
> user=> (def s "foobar")
> #'user/s
>
> user=> (s.replace "o" "e")
> "feebar"

$ kawa
#|kawa:1|# (define s "foobar")
#|kawa:2|# (s:replace "o" "e")
feebar

> The net result is much more of an integrated feel than one language
> bridging to another.
>
> You can find out more at:
>
> http://clojure.org

http://www.gnu.org/software/kawa/

Rich Hickey

unread,
Apr 29, 2008, 9:42:18 PM4/29/08
to JVM Languages
It is listed there, in the functional programming section.

Rich

Randall R Schulz

unread,
Apr 29, 2008, 9:55:49 PM4/29/08
to jvm-la...@googlegroups.com

D'Oh! I recently installed the regular-expression search extension
(called /Find Bar/) to Firefox, and had the case-sensitive option on.

Sorry...


> Rich


RRS

Rich Hickey

unread,
Apr 30, 2008, 12:20:16 AM4/30/08
to JVM Languages
On Apr 29, 8:45 pm, Per Bothner <p...@bothner.com> wrote:
> Rich Hickey wrote:
>
> [Hope you'll forgive me making this an excuse for a competitive
> comparison ...]
>

I have nothing but respect for Kawa and the work you've done there. It
is my first recommendation for those looking for Scheme on the JVM.
Given good implementations like Kawa and SISC, I wouldn't have
undertaken Clojure if I didn't intend to produce something more
significant than yet another minor Scheme variant. Clojure is a very
different Lisp with many enhancements over older Lisps.

A critical enhancement, and one that is difficult to retrofit, is a
point you skipped over in your comparison - the extension of the
sequence library to an abstraction of first/rest, freeing it from its
traditional binding to concrete cons cells. This goes directly to the
deeper integration I spoke of. For instance, here's one way to pull
all of the System properties keys whose names match some regular
expression:

(filter #(re-find #"java" %) (map key (System.getProperties)))

-> ("java.runtime.name" "java.vm.version" "java.vm.vendor" ...)

And here's one way to add the entries at those keys into a Clojure
map:

(reduce conj {}
(filter #(re-find #"java" (key %)) (System.getProperties)))

-> {"java.specification.version" "1.5",
"java.vm.specification.name" "Java Virtual Machine
Specification",
...}

It's functional and idiomatic Lisp. The filter, reduce and map
functions are the very same ones that work on all Clojure data
structures, and the key function the same one that works on Clojure
maps.

Clojure is a functional language. Its data structures are immutable
and persistent. It extends the core Lisp data types to (immutable,
persistent) vectors, hashed and sorted maps and sets, all with deep
code-as-data support. The sequence library, in addition to being
abstraction based, is lazy and obviates add-on stream libraries. It
has a software transactional memory and agent system, metadata,
pervasive destructuring binding, list comprehensions, regexes etc.

Kawa is great, but it's not a substitute for, nor superset of,
Clojure.

I'm happy to let the rest of this 'competition' play out in the
marketplace of users.

Regards,

Rich

Per Bothner

unread,
Apr 30, 2008, 2:06:19 AM4/30/08
to jvm-la...@googlegroups.com
Rich Hickey wrote:
> A critical enhancement, and one that is difficult to retrofit, is a
> point you skipped over in your comparison - the extension of the
> sequence library to an abstraction of first/rest, freeing it from its
> traditional binding to concrete cons cells. This goes directly to the
> deeper integration I spoke of. For instance, here's one way to pull
> all of the System properties keys whose names match some regular
> expression:
>
> (filter #(re-find #"java" %) (map key (System.getProperties)))
>
> -> ("java.runtime.name" "java.vm.version" "java.vm.vendor" ...)

I'm very supportive of this kind of abstraction, and I've been
playing with these issues for more years than I care to admit ...

Kawa has some attempts in this direction, though not as
completely or consistently as I'd like. I.e. the 'map'
function implements the Scheme map function over Scheme-type lists,
rather than a general map over java.util.List.

I actually don't think this enhancement would be difficult to retrofit
to Kawa. I've already "planned" (i.e. it's on my wish-list) making
<pair> an abstract class. (One benefit is it would make it easier
to write hygienic macros.) And as mentioned <pair> already implements
java.util.List.

> Clojure is a functional language. Its data structures are immutable
> and persistent. It extends the core Lisp data types to (immutable,
> persistent) vectors, hashed and sorted maps and sets, all with deep
> code-as-data support. The sequence library, in addition to being
> abstraction based, is lazy and obviates add-on stream libraries.

You might find the gnu/lists package of Kawa interesting.

> It has a software transactional memory and agent system, metadata,
> pervasive destructuring binding, list comprehensions, regexes etc.

These all sound like nice features - the kind I'd like to have
in Kawa.

> I'm happy to let the rest of this 'competition' play out in the
> marketplace of users.

Perhaps a friendly merger might be possible?

Patrick Wright

unread,
Apr 30, 2008, 2:30:17 AM4/30/08
to jvm-la...@googlegroups.com
> Because of this I'd like to use a Lisp dialect to add scripting. Right
> now, I'm looking mostly at SISC and Kawa.

I don't know if the author(s) of SISC are following this list--I don't
recall them speaking up or presenting SISC--an invitation to them
might be in order.


Patrick

David Huebel

unread,
Apr 30, 2008, 3:35:30 AM4/30/08
to jvm-la...@googlegroups.com
On Tue, Apr 29, 2008 at 5:08 PM, Randall R Schulz <rsc...@sonic.net> wrote:
> > Does the application use classloaders in interesting ways that might
> > trip up the language implementation?
>
> My application does not, but the fact that its deployed in a servlet
> container might make the answer a de facto "yes." I'm not sure.

I haven't programmed servlets in a long time, but I seem to remember
that they use classloaders to isolate different components so that
sharing of class libraries between components is limited to classes
loaded by the framework. Code from one component must be executed
using the appropriate classloader for that component, or you'll get
class incompatibility errors (or more insidiously, class compatibility
errors, where components that are supposed to be isolated interact
through a class library's global state.) A language implementation
that insists on using a single classloader for executing all code
might not work in that environment, or it might force all users of the
language to cooperate and share class libraries.

At first glance, the classloader-level isolation provided by a servlet
container (or other application framework) should enable you to load
two completely independent instances of the same language
implementation, each with its own base classloader, but I don't know
if that holds true in the face of all the techniques used by JVM
language implementors. If it doesn't hold true for a given language
implementation, then the implementation violates a widespread
assumption about how software components act on the Java platform, and
it is unlikely to play well with existing Java application frameworks.

-David

Rich Hickey

unread,
Apr 30, 2008, 9:26:48 AM4/30/08
to JVM Languages

On Apr 30, 2:06 am, Per Bothner <p...@bothner.com> wrote:

>
> Perhaps a friendly merger might be possible?

I think peaceful coexistence is more likely. Clojure has certainly
ceded the backwards-compatibility ground.

There was a time (you may not remember) when I was considering either
implementing in Kawa or utilizing its infrastructure. But I also
wanted to support .Net, so I went off and reinvented a Lisp core in C#/
Java. Along the way, I turned Clojure into a functional language, and
dropped .Net.

I don't think I could get the benefits I want from Clojure if it were
just a library on a language that didn't embrace functional
programming and immutability in its core feature set. In this respect
Clojure has fundamentally diverged from CL/Scheme.

Rich

Charles Oliver Nutter

unread,
Apr 30, 2008, 9:44:24 AM4/30/08
to jvm-la...@googlegroups.com
Rich Hickey wrote:
>
> On Apr 30, 2:06 am, Per Bothner <p...@bothner.com> wrote:
>
>> Perhaps a friendly merger might be possible?
>
> I think peaceful coexistence is more likely. Clojure has certainly
> ceded the backwards-compatibility ground.
>
> There was a time (you may not remember) when I was considering either
> implementing in Kawa or utilizing its infrastructure. But I also
> wanted to support .Net, so I went off and reinvented a Lisp core in C#/
> Java. Along the way, I turned Clojure into a functional language, and
> dropped .Net.

Sounds like there's a story there. As I understand it, Scala's .NET
support has been mostly abandoned too. Care to elaborate? Was it just
one too many platforms to support, or were there any technical reasons
you stuck to the Java side?

- Charlie

Charles Oliver Nutter

unread,
Apr 30, 2008, 9:45:06 AM4/30/08
to jvm-la...@googlegroups.com

I did send out an invitation when the group was started, but perhaps
someone closer to the project could give it another go?

- Charlie

Rich Hickey

unread,
Apr 30, 2008, 11:53:07 AM4/30/08
to JVM Languages


On Apr 30, 9:44 am, Charles Oliver Nutter <charles.nut...@sun.com>
wrote:
Clojure was originally written in Common Lisp and generated C#/Java
code. I developed the runtime libraries in Java and hand-ported to C#
as I went. It was tedious, but the differences between C# and Java
were mostly (annoyingly) superficial. However, it was a constant 40%
drain on my time to constantly have to restate everything slightly
differently for MS's behalf.

At some point I decided that, after the core was finished, Clojure
would be growing primarily in libraries, and that there would be found
the greatest set of differences between the platforms. So I guess I
made the opposite decision than did the Fan developers, and decided it
would be better to have libraries deeply leverage a single platform
rather than have everyone that contributed to Clojure have to face the
same 40% porting overhead, never mind all the complexity of
understanding and unifying the semantics of slightly different
infrastructures. It seemed to me one platform would invariably be
preferred, the other the port target, and I might as well just choose
one. Doing so would also allow me to more deeply integrate Clojure
with the type system and library hierarchy of the host platform.

Choosing Java over the CLR was easy. In my opinion:

Java has greater platform reach.

Java is more dynamic. Java's dynamic loading heritage pervades the
platform in many subtle ways.

Java has much more open source activity, many more libraries to
leverage. Java itself becoming open source clinched the deal of it
becoming the open-source target platform of choice.

Java's core data structure library and concurrency stuff is much
better, and its memory model better defined (a big issue once I got
into STM).

Java has a simpler VM architecture, greatly easing interop. Things
like CLR value types and the way they do generics might provide a 10%
perf advantage (or might not), but definitely double the complexity.
Java's generics via erasure are a blessing for dynamic languages.

I eventually decided to generate bytecode on-the-fly and found ASM
much nicer than anything on the CLR side, and, again, a better dynamic
loading story. Differences in bytecode between the platforms are much
bigger than between C#/Java source code, so maintaining a port would
have been much harder still.

Having dropped the CLR, I've never regretted it. Progress on Clojure
proceeded rapidly. I'm very happy with HotSpot, on-the-fly
compilation, library availability, community, portability etc.

Rich

Randall R Schulz

unread,
Apr 30, 2008, 12:22:33 PM4/30/08
to jvm-la...@googlegroups.com
On Tuesday 29 April 2008 14:07, Randall R Schulz wrote:
> ...

Thanks everyone for the feedback, especially for being made aware of
Clojure.

I'll be looking into these three languages (in alphabetic order, of
course):

- Clojure
- Kawa
- SISC


Randall Schulz

Charles Oliver Nutter

unread,
Apr 30, 2008, 1:00:07 PM4/30/08
to jvm-la...@googlegroups.com
Very interesting response, Rich... Thank you. Comments below.

Rich Hickey wrote:
> Java has greater platform reach.

Undoubtedly, and I think the work we're all doing will help keep it
strong and extend it further.

> Java is more dynamic. Java's dynamic loading heritage pervades the
> platform in many subtle ways.

Interesting...would you care to elaborate? I agree, but for mostly
intangible reasons. I have not worked in an environment that did not
support dynamic loading of code (or not as dynamic as Java) for a long
time. But I remember my C and C++ days, and whenever I look at C/C++
projects now I can't imagine being that statically bound. My impression
is that C#/.NET has similar (if perhaps slightly lessened) restrictions.

> Java has much more open source activity, many more libraries to
> leverage. Java itself becoming open source clinched the deal of it
> becoming the open-source target platform of choice.

I was also very excited about the open-sourcing. I think as a result
we'll see JDKs on a lot more systems, more pervasively distributed, and
the platform will grow tremendously. And I think this will be a big year
for OpenJDK in general, what with DVM and the OpenJDK Challenge.

> Java's core data structure library and concurrency stuff is much
> better, and its memory model better defined (a big issue once I got
> into STM).
>
> Java has a simpler VM architecture, greatly easing interop. Things
> like CLR value types and the way they do generics might provide a 10%
> perf advantage (or might not), but definitely double the complexity.
> Java's generics via erasure are a blessing for dynamic languages.

AMEN. From Java, I sometimes lament erasure because it limits how
intelligently the language can work with generic types. But as a dynlang
implementer...I see the contortions IronRuby and IronPython need to do
because they're *forced* to support full generic type instantiation, and
it makes me weep. Whatever happens with "erasing erasure" the
non-parameterized fallback *MUST* remain.

> I eventually decided to generate bytecode on-the-fly and found ASM
> much nicer than anything on the CLR side, and, again, a better dynamic
> loading story. Differences in bytecode between the platforms are much
> bigger than between C#/Java source code, so maintaining a port would
> have been much harder still.

I have not looked at CLR IL generation, but I do like ASM a lot. JRuby
uses ASM extensively for generating method handles and obviously for the
compiler itself.

What bytecode-level differences do you think would have been the largest
issues? I understand that CLR has statically-typed local variables at
the bytecode level too, so that's probably one (JRuby is *very* liberal
about what it stuffs in local variables). And I would imagine IL
reflects the much-more-static nature of CLR. Having investigated it
yourself, I'd be interested in hearing your take.

> Having dropped the CLR, I've never regretted it. Progress on Clojure
> proceeded rapidly. I'm very happy with HotSpot, on-the-fly
> compilation, library availability, community, portability etc.

Well I'm very glad you're on the group. You may want to join the MLVM
list as well, since the Da Vinci Machine patches are starting to fly there.

- Charlie

Brian Frank

unread,
Apr 30, 2008, 3:17:27 PM4/30/08
to JVM Languages
> projects now I can't imagine being that statically bound. My impression
> is that C#/.NET has similar (if perhaps slightly lessened) restrictions.

I don't think .NET is any less dynamic than the JVM - you can load
assemblies and types on the fly just like Java. But the execution of
this feature on .NET isn't nearly as nice as the JVM. For example, if
you are using the emit APIs you have a lot less flexibility to lazy
load types. In Java you can make references to external types,
methods, fields and they are loaded when needed. In .NET you can't
emit those references unless you also emit what is being referenced -
it kind of turns into a big hairball. And I've mentioned before you
have to generate a file on disk to get line numbers which seems silly
- you can't do strictly in memory.

> What bytecode-level differences do you think would have been the largest
> issues? I understand that CLR has statically-typed local variables at
> the bytecode level too, so that's probably one (JRuby is *very* liberal
> about what it stuffs in local variables). And I would imagine IL
> reflects the much-more-static nature of CLR. Having investigated it
> yourself, I'd be interested in hearing your take.

Yes indeed you need to emit typed local variable definitions -
although I haven't found it too bad. It isn't much different that
what the JVM verifier expects. And I expect some of the future JVM
"pre-verification meta-data" will amount to the same thing.

Another thing is that to compile something like "a = b[c] = d"
requires a bit of stack manipulation to leave the value of d on the
stack for assignment to a. In Java this is pretty easy. On the CLR
it requires generating a local variable because you can't really
manipulate the stack.

There are also special opcodes for leaving try/finally blocks that are
a bit twisted, but they aren't that bad.

Rodrigo B. de Oliveira

unread,
Apr 30, 2008, 4:20:11 PM4/30/08
to jvm-la...@googlegroups.com
On Wed, Apr 30, 2008 at 4:17 PM, Brian Frank <brian...@gmail.com> wrote:
>
> > projects now I can't imagine being that statically bound. My impression
> > is that C#/.NET has similar (if perhaps slightly lessened) restrictions.
>
> I don't think .NET is any less dynamic than the JVM - you can load
> assemblies and types on the fly just like Java.

Assemblies are not subject to garbage collection.

Charles Oliver Nutter

unread,
May 1, 2008, 12:12:13 AM5/1/08
to jvm-la...@googlegroups.com

A powerful distinction...classloaders can load arbitrary code and go
away when that code and the classloader itself are dereferenced. If they
couldn't we'd have a *devil* of a time supporting a JIT mode in JRuby.

How does the DLR get around this when generating DynamicSites?

- Charlie

Antonio Cuni

unread,
May 3, 2008, 3:32:25 AM5/3/08
to jvm-la...@googlegroups.com
Charles Oliver Nutter wrote:

> How does the DLR get around this when generating DynamicSites?

AFAIK, the DLR makes heavy use of DynamicMethod, which are a kind of
methods that are not bound to a particular assembly and can be garbage
collected freely.

ciao,
Anto

Reply all
Reply to author
Forward
0 new messages