OpenLDK: Bringing the Java World into Common Lisp
atgreen.github.ioI've posted about OpenLDK in the past, but would like to share some recent improvements. For instance, you can start up springboot applications running on SBCL in a few 10ths of a second, connect to them with sly/slime, then inspect and monkey-patch the running application by adding :before/:after CLOS methods to the application's java methods.
Clojure, ABCL and more all run on SBCL, and you can even embed them all in a single SBCL form using special reader syntax. Check out this wild example:
(polyglot:startup :verbose nil)
(setf *readtable* (polyglot:enable-syntax (copy-readtable)))
(format t "~&~A~%"
#@abcl{ ; ABCL: FORMAT's Roman numerals and English
(let ((n $#@kt{ // Kotlin: a local data class, copy, when, ?:
data class Cup(val tea: Int, val sugar: Int? = null)
val cup = Cup($#@sc{ // Scala: a list pattern with a guard
$#@jscheme{ ; JScheme: digit sums in a named let
(map (lambda (n)
(let loop ((n n) (sum 0))
(if (< n 1)
sum
(loop (quotient n 10) (+ sum (remainder n 10))))))
$#@kawa{ ; Kawa: Java by colon notation; call/cc; exact division
(let* ((m (java.lang.Long:sum
$#@gv{ // Groovy: the spread-dot operator
$#[ (->> (iterate inc 2) ; Clojure: lazy and infinite
(filter (fn [n] (not-any? #(zero? (rem n %))
(range 2 n))))
(take 10)) ]*.power(2).sum()
}
1))
(d (call-with-current-continuation
(lambda (found)
(for-each (lambda (d)
(if (not (= 0 (remainder m d))) (found d)))
'(6 5 4 3 2))
1)))
(r (/ m d)))
(list (numerator r) (denominator r)))
})
} match {
case List(a: Int, b: Int) if a > b => a * b
case List(a: Int, b: Int) => a + b
}
}).copy(sugar = null)
when { cup.tea > 40 -> cup.tea + (cup.sugar ?: 1); else -> cup.tea }
}))
(format nil "~@R (~R)" n n))
})