понеділок, 12 листопада 2012 р.

Helping Java build friendship with Common Lisp

When I was 3rd year student I had functional programming and AI classes where we studied Common Lisp programming language. At the end of AI course I had coursework: write program to calculate differential expression, something like f(x) = x*x then f'(x)=2*x. It was pretty simple to do in Lisp...


As business layer was implemented in Lisp I decided to create user interface in Java. I had to use Swing, because JavaFX didn't exist at this time. So, I guess I started hate Swing from this time...
But here I'd like to show how you can execute Common Lisp from Java (from my personal experience with code sample and some other options). So, how to use Lisp from Java?

   I found amazing library Jatha, it's open source library located at http://jatha.sourceforge.net/. This library provides powerful of Lisp in your java code. Let's look at usage example (from my course work).
This is a part of Lisp program:
;; the prototype function mydiff, release you can see down
(defun mydif (l x) ())
;; these functions differentiation l-expression for x
(defun dif* (l x)
;; resultate is: (+ (* a' b) (* a b'))
(list
(list (mydif (first l) x) '* (third l))
'+
(list (mydif (third l) x) '* (first l))
)
)
(defun dif+ (l x)
;; resultate is: (+ a' b')
(list (mydif (first l) x) '+ (mydif (third l) x))
)
(defun dif- (l x)
;; resultate is: (- a' b')
(list (mydif (first l) x) '- (mydif (third l) x))
)
(defun dif/ (l x)
; resultate is: (/ (- (* a' b) (* a b')) (^ b 2))
(list
(list
(list (mydif (first l) x) '* (third l) )
'-
(list (mydif (third l) x) '* (first l) )
)
'/
(list (third l) '^ 2)
)
)
;; this function any simplify l-expression
(defun simplify(l)
(cond
((atom l) l)
((eql (second l) '*)
(cond
((eql (first l) 0) 0)
((eql (third l) 0) 0)
((eql 1 (first l)) (simplify (third l)))
((eql 1 (third l)) (simplify (first l)))
((and (numberp (first l)) (numberp (third l))) (* (first l) (third l)))
(t (list (simplify (first l)) '* (simplify (third l))))
)
)
((eql (second l) '+)
(cond
((eql (first l) 0) (simplify (third l)))
((eql (third l) 0) (simplify (first l)))
((and (numberp (first l)) (numberp (third l))) (+ (first l) (third l)))
(t (list (simplify (first l)) '+ (simplify (third l))) )
)
)
((eql (second l) '-)
(cond
((eql (third l) 0) (simplify (first l)))
((eql (first l) (third l)) 0)
((and (numberp (first l)) (numberp (third l))) (- (first l) (third l)))
(t
(cond
((null (third l)) (list '- (simplify (first l))) )
(t (list (simplify (first l)) '- (simplify (third l))))
)
)
)
)
((eql (second l) '/)
(cond
((eql (first l) 0) 0)
((eql (first l) (third l)) 1)
((and (numberp (first l)) (numberp (third l))) (/ (first l) (third l)))
(t (list (simplify (first l)) '/ (simplify (third l))))
)
)
(t l)
)
)
;; main function for differentiation l-expression for x
(defun mydif (l x)
(simplify (simplify
(cond
((atom l) (if (eq l x) 1 0))
((null (second l)) (first l))
((eq (second l) '+) (dif+ l x))
((eq (second l) '*) (dif* l x))
((eq (second l) '-) (dif- l x))
((eq (second l) '/) (dif/ l x))
...
(t '(illegal operation))
)
))
)
view raw gistfile1.lisp hosted with ❤ by GitHub

And how we can reuse Lisp power inside Java-code:
private static final String lispSource = "diff.lisp";
public String evalResult(String expression, String dif)
{
LispValue resultat = null;
try
{
String input = "(mydif '" + expression + " '" + dif + ")"; // diff expression by dif
LispValue T = myLisp.load(this.loadLispSource(lispSource));
resultat = myLisp.eval(input);
}
catch(Throwable ex)
{
...
}
return resultat.toString();
}
view raw gistfile1.java hosted with ❤ by GitHub

As you can see it's very-very easy. So, here I'd like to say 'Thank you!' to creators for Jatha
However, some Common Lisp functionality is lack in this library, for example mapcar and cond not implemented and you will need to create your own if need

Another way is to use ABCL. ABCL is a Common Lisp implementation that runs directly in the JVM - possibly it is the best option to run Common Lisp side by side with Java. I haven't ever used it myself, but a lot of people have a positive experience.

Finally, If you don't need exactly Common Lisp, and you are ok with Scehme, you must look at JScheme. The API is so easy as Jatha and you should be able to use all Scheme power just from Java code.

2 коментарі:

  1. Відповіді
    1. Clojure appeared in 2007
      даний код писався в тому ж році, коли про Clojure мало хто чув (якщо він взагалі згадувався гуглом)

      Видалити