Greetings,
I've been playing around with ABCL for some days now, especially in terms of the Java interop abilities and Swing. This is because I was searching for a Lisp that could be easily used for cross-platform GUI programming and easy deployed (for the user). This narrowed it down to the several JVM-based Lisps (ABCL, Kawa, etc) and Clojure.
While I like Clojure - and "lein uberjar" is a great facility, for example - I'm more confortable in CL, so I did this two small examples that can perhaps be useful as a way to compare ABCL's different interop facilities with themselves and Clojure. In a way I used this to get a "feel" on how things would work out and make a decision.
ABCL JSS Swing Example: http://paste.lisp.org/display/130606 ABCL JFLI Swing Example: http://paste.lisp.org/display/130605
I'm going to make another use using the lower-level API (jcall, etc), for the sake of completeness, but I think that perhaps this examples can be helpful to others as a small reference, using a well-known example. For me it was quite fun and my overall impressions thus far is that:
1) ABCL offers different interop facilities that taken as a whole make it a quite capable solution for overall Java interop, including GUI programming.
2) The JSS approach has the advantage of being less verbose since the methods need not contain the class name (which looks cleaner IMO). It is also simpler to setup, i.e. no need for def-java-class et. al.
3) The JFLI approach integrates well with Lisp, since it provides completion of methods, amongst other small things. The lack of #"foo" syntax is also visually appealing IMO. It can also - theoretically - be used by JFLI installations in other Lisps. It is more verbose though, since methods must be preceeded with the class (class.foomethod)
4) Clojure's approach is (naturally) conceptually quite similar to JFLI, in the "feel" that it provides, although the use of (.fooMethod instance) is similar to (#"fooMethod" instance) in terms of synxtax. The use of macros (like doto) significantly reduces number of words used.
5) I see nothing in the way of implementing similar macro mechanisms on top of either JSS or JFLI - but I can be simplifying things brutally here.
In the most simple scenario syntax differences are as follows:
ABCL JSS: (#"setText" my-label "The Larch") ABCL JFLI: (jlabel.settext my-label "The Larch") Clojure: (.setText my-label "The Larch")
The Clojure approach seems quite similar to the javadot approach of jscheme (http://jscheme.sourceforge.net/jscheme/doc/javadot.html), as noted in the ABCL blog - I was unaware of that.
More complex approachs envolving the need for proxies contain more differences of course.
I would greatly welcome any comments concerning style and approach: I am completely new to this so I am probably missing a lot. It was quite enjoyable though, even if there are still some rough edges here and there (quite understandable since for JFLI I had to used trunk). I think that this is an area worth exploration, easy (meaning well-integrated, clear syntax, small impact) interop is a huge advantage.
Thank you for your hard work, highly appreciated.
Cheers,
Frederico
On Fri, Jul 20, 2012 at 4:22 PM, Frederico Muñoz fsmunoz@gmail.com wrote:
Greetings,
I've been playing around with ABCL for some days now, especially in terms of the Java interop abilities and Swing. This is because I was searching for a Lisp that could be easily used for cross-platform GUI programming and easy deployed (for the user). This narrowed it down to the several JVM-based Lisps (ABCL, Kawa, etc) and Clojure.
While I like Clojure - and "lein uberjar" is a great facility, for example - I'm more confortable in CL, so I did this two small examples that can perhaps be useful as a way to compare ABCL's different interop facilities with themselves and Clojure. In a way I used this to get a "feel" on how things would work out and make a decision.
ABCL JSS Swing Example: http://paste.lisp.org/display/130606 ABCL JFLI Swing Example: http://paste.lisp.org/display/130605
This is great, thank you very much for taking the time to write these examples!
I'm going to make another use using the lower-level API (jcall, etc), for the sake of completeness, but I think that perhaps this examples can be helpful to others as a small reference, using a well-known example. For me it was quite fun and my overall impressions thus far is that:
- ABCL offers different interop facilities that taken as a whole make
it a quite capable solution for overall Java interop, including GUI programming.
- The JSS approach has the advantage of being less verbose since the
methods need not contain the class name (which looks cleaner IMO). It is also simpler to setup, i.e. no need for def-java-class et. al.
I think the current incarnation of JSS is mainly a layer above jcall etc. - BUT it can be more efficient than naive use of the native Java FFI because it knows how to cache reflection metaobjects (e.g. methods). I don't know the details, though.
- The JFLI approach integrates well with Lisp, since it provides
completion of methods, amongst other small things. The lack of #"foo" syntax is also visually appealing IMO. It can also - theoretically - be used by JFLI installations in other Lisps. It is more verbose though, since methods must be preceeded with the class (class.foomethod)
Interesting. I had looked at JFLI ages ago, before I started using ABCL, but I don't know much about it.
But really, I think the class-name-followed-by-dot prefix is a design smell. I think that a Java class should be mapped to a Lisp package, and methods and fields to symbols in that package (perhaps inherited from another package following Java inheritance). Then, you would have the options to write
(java.lang.Comparable:compare-to x y) (Comparable:compare-to x y) ;Assuming a package nickname (compare-to x y) ;If you imported the symbol or used the whole package
You could also map Java access modifiers to symbol visibility:
public -> external protected -> internal, but explicitly imported in subpackages private, default -> internal
- Clojure's approach is (naturally) conceptually quite similar to
JFLI, in the "feel" that it provides, although the use of (.fooMethod instance) is similar to (#"fooMethod" instance) in terms of synxtax. The use of macros (like doto) significantly reduces number of words used.
ABCL could certainly benefit from more high-level macros. Right now we only have java:chain that allows you to chain method invocations, like some Clojure operator I don't remember (->> or something) and like a.b(x).c(y).d(z) in Java.
- I see nothing in the way of implementing similar macro mechanisms on
top of either JSS or JFLI - but I can be simplifying things brutally here.
In the most simple scenario syntax differences are as follows:
ABCL JSS: (#"setText" my-label "The Larch") ABCL JFLI: (jlabel.settext my-label "The Larch") Clojure: (.setText my-label "The Larch")
The Clojure approach seems quite similar to the javadot approach of jscheme (http://jscheme.sourceforge.net/jscheme/doc/javadot.html), as noted in the ABCL blog - I was unaware of that.
Yep. Personally I don't like it very much, because it's more stuff than a simple reader macro...
More complex approachs envolving the need for proxies contain more differences of course.
I would greatly welcome any comments concerning style and approach: I am completely new to this so I am probably missing a lot. It was quite enjoyable though, even if there are still some rough edges here and there (quite understandable since for JFLI I had to used trunk). I think that this is an area worth exploration, easy (meaning well-integrated, clear syntax, small impact) interop is a huge advantage.
You might want to look at the java.lisp file. It contains a bunch of interesting and not widely known operators. ABCL's FFI is really more than just invocation of methods; you can, among other things:
- implement interfaces with proxies - specialize CLOS generic functions on Java classes - use Java lists as sequences - write Java classes in Lisp (this is work in progress)
There are also a couple of pages in the abcl wiki that I wrote or contributed to, but they're incomplete unfortunately.
Best, Alessio
Thank you for your hard work, highly appreciated.
Cheers,
Frederico
armedbear-devel mailing list armedbear-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/armedbear-devel
Greetings,
Thank you for your answer!
Alessio Stalla alessiostalla@gmail.com writes:
This is great, thank you very much for taking the time to write these examples!
My pleasure, I'm glad you found them worthwhile. I was also surprised to see this post in Planet Lisp via Zach Beane's blog, which was cool :)
I think the current incarnation of JSS is mainly a layer above jcall etc. - BUT it can be more efficient than naive use of the native Java FFI because it knows how to cache reflection metaobjects (e.g. methods). I don't know the details, though.
I didn't even considered anything related to performance. For my purposes in terms of simple GUI programming I would not mind trading some performance for overall ease of use though... well, depending on the real difference in terms of user experience of course.
Having said that, it would be interesting to benchmark the different APIs.
Interesting. I had looked at JFLI ages ago, before I started using ABCL, but I don't know much about it.
Since it's Rich Hickey's work before Clojure it is interesting to compare, and since ABCL recently incorportated it I was intrigued by it.
But really, I think the class-name-followed-by-dot prefix is a design smell. I think that a Java class should be mapped to a Lisp package, and methods and fields to symbols in that package (perhaps inherited from another package following Java inheritance). Then, you would have the options to write
(java.lang.Comparable:compare-to x y) (Comparable:compare-to x y) ;Assuming a package nickname (compare-to x y) ;If you imported the symbol or used the whole package
You could also map Java access modifiers to symbol visibility:
public -> external protected -> internal, but explicitly imported in subpackages private, default -> internal (...)
That's not entirely unlike what JFLI does: I'm using (use-package "javax.swing") since JFLI maps Java packages to CL packages; what you are proposing is the mapping of Java *classes* to CL packages, which I agree would reduce the "clutter" somewhat, especially because it is IMO a bit strange to have to specificy the class of a method *and* provide the object that receives it.
JFLI seems to go to great lenghts to integrate itself into CL packages, etc. I'm still exploring it though. JSS OTOH "just works", it's simple to use and does what it is supposed to (JFLI requires a bit more setup).
ABCL could certainly benefit from more high-level macros. Right now we only have java:chain that allows you to chain method invocations, like some Clojure operator I don't remember (->> or something) and like a.b(x).c(y).d(z) in Java.
Didn't knew about java:chain, thank you - I'm still reading about the java interop facilities, my impression is that there is a lot under the hood that isn't known (and thus not used). I'm still going to add the "low level" example that uses jcall, jmethod, etc.
In the most simple scenario syntax differences are as follows:
ABCL JSS: (#"setText" my-label "The Larch") ABCL JFLI: (jlabel.settext my-label "The Larch") Clojure: (.setText my-label "The Larch") (...)
Yep. Personally I don't like it very much, because it's more stuff than a simple reader macro...
True. I think that the ability to simple use (settext my-label "The Larch") would be great, but I suspect that if this was simple it would already be done ;)
A bit OT, but not unlike another obvious idea, which would be to support CLIM using Java interop and Swing, thus making code targeted at ABCL universal in both ways: completely self-contained due to the JVM, and also able to be deployed in other CL implementations. This would IMO be something that would make the "CL hosted on the JVM" really shine.
This assumes that CLIM is actually 1) a standard and 2) a good approach to GUI programming, something that can be debated
You might want to look at the java.lisp file. It contains a bunch of interesting and not widely known operators. ABCL's FFI is really more than just invocation of methods; you can, among other things:
- implement interfaces with proxies
- specialize CLOS generic functions on Java classes
- use Java lists as sequences
- write Java classes in Lisp (this is work in progress)
There are also a couple of pages in the abcl wiki that I wrote or contributed to, but they're incomplete unfortunately.
Thank you, I will do that. As I mentioned preivously perhaps my (completely trivial) experimentation can help in uncovering hidden functionality with examples, etc. The CLOS specialisation seems extremely interesting BTW.
"Write Java classes in Lisp"... this is, I must confess, where I am stuck at the moment. I'm trying to make another, slightly more complex, example that involves a canvas-like interface. For this the examples I find (in Java) imply overriding the paintComponent method of JPanel. This is something that apparently can't be made by using interfaces, I need a new class (or proxy). I can't seem to find how to do this in ABCL - at least using JSS or JFLI. This is such a deal breaker that I am surely missing something obvious.
BTW, I've read some of your material in Snow, I haven't gone for that route yet since before using a framework I want to understand the gory details, but it's very helpful.
Thank you and best regards,
Frederico
On 31 Jul 2012, at 18:39, fsmunoz@gmail.com (Frederico Muñoz) wrote: [...]
A bit OT, but not unlike another obvious idea, which would be to support CLIM using Java interop and Swing, thus making code targeted at ABCL universal in both ways: completely self-contained due to the JVM, and also able to be deployed in other CL implementations. This would IMO be something that would make the "CL hosted on the JVM" really shine.
This assumes that CLIM is actually 1) a standard and 2) a good approach to GUI programming, something that can be debated
Funnily enough, McCLIM was my motivation for implementing the MOP for abcl. Even if turns out not to be practical, a clim running on the jvm has serious hack value. :)
Rudi
Hi,
As an addition to the discussion, see http://paste.lisp.org/display/130806in which I define a macro that behaves like doto for this example. Note that the JSS lisp paste had a typo - s/setsize/setSize/
This addresses your point 5 - macros are always possible ;-)
The main reason that I didn't use the dot notation for jss was that I don't want to live with a case sensitive reader all the time. OTOH if someone wants to offer up a readtable that reads case-sensitive at the right times (like after the "." for a symbol in the function position), that might be interesting to try.
Note that #"foo" reads as funcallable function - e.g. you can write
(funcall #"foo" arg1 arg2...)
Are the dot functions also regular functions in closure, or are they special forms?
-Alan
On Fri, Jul 20, 2012 at 10:22 AM, Frederico Muñoz fsmunoz@gmail.com wrote:
Greetings,
I've been playing around with ABCL for some days now, especially in terms of the Java interop abilities and Swing. This is because I was searching for a Lisp that could be easily used for cross-platform GUI programming and easy deployed (for the user). This narrowed it down to the several JVM-based Lisps (ABCL, Kawa, etc) and Clojure.
While I like Clojure - and "lein uberjar" is a great facility, for example - I'm more confortable in CL, so I did this two small examples that can perhaps be useful as a way to compare ABCL's different interop facilities with themselves and Clojure. In a way I used this to get a "feel" on how things would work out and make a decision.
ABCL JSS Swing Example: http://paste.lisp.org/display/130606 ABCL JFLI Swing Example: http://paste.lisp.org/display/130605
I'm going to make another use using the lower-level API (jcall, etc), for the sake of completeness, but I think that perhaps this examples can be helpful to others as a small reference, using a well-known example. For me it was quite fun and my overall impressions thus far is that:
- ABCL offers different interop facilities that taken as a whole make
it a quite capable solution for overall Java interop, including GUI programming.
- The JSS approach has the advantage of being less verbose since the
methods need not contain the class name (which looks cleaner IMO). It is also simpler to setup, i.e. no need for def-java-class et. al.
- The JFLI approach integrates well with Lisp, since it provides
completion of methods, amongst other small things. The lack of #"foo" syntax is also visually appealing IMO. It can also - theoretically - be used by JFLI installations in other Lisps. It is more verbose though, since methods must be preceeded with the class (class.foomethod)
- Clojure's approach is (naturally) conceptually quite similar to
JFLI, in the "feel" that it provides, although the use of (.fooMethod instance) is similar to (#"fooMethod" instance) in terms of synxtax. The use of macros (like doto) significantly reduces number of words used.
- I see nothing in the way of implementing similar macro mechanisms on
top of either JSS or JFLI - but I can be simplifying things brutally here.
In the most simple scenario syntax differences are as follows:
ABCL JSS: (#"setText" my-label "The Larch") ABCL JFLI: (jlabel.settext my-label "The Larch") Clojure: (.setText my-label "The Larch")
The Clojure approach seems quite similar to the javadot approach of jscheme (http://jscheme.sourceforge.net/jscheme/doc/javadot.html), as noted in the ABCL blog - I was unaware of that.
More complex approachs envolving the need for proxies contain more differences of course.
I would greatly welcome any comments concerning style and approach: I am completely new to this so I am probably missing a lot. It was quite enjoyable though, even if there are still some rough edges here and there (quite understandable since for JFLI I had to used trunk). I think that this is an area worth exploration, easy (meaning well-integrated, clear syntax, small impact) interop is a huge advantage.
Thank you for your hard work, highly appreciated.
Cheers,
Frederico
armedbear-devel mailing list armedbear-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/armedbear-devel
armedbear-devel@common-lisp.net