```Scheme 在 Java 上 在 Common Lisp```
Cl-kawa: Scheme on Java on Common Lisp

原始链接: https://github.com/atgreen/cl-kawa

## cl-kawa: Common Lisp 与 Scheme 互操作 cl-kawa 是一个技术演示,它能够在单个 SBCL 进程内实现 Common Lisp 和 Kawa Scheme 之间的深度互操作。它利用 OpenLDK(Common Lisp 中的 JVM 实现)来转译 Java 字节码,并允许在两种语言之间进行无序列化或进程边界的无缝调用。 主要特性包括:从 Common Lisp 评估 Scheme 表达式(作为字符串或 S 表达式),调用 Scheme 过程,以及在 Scheme 中注册 Common Lisp 函数。基本数据类型(如数字、字符串、布尔值和列表)可以直接交换。一个“Hello World”示例展示了跨 Common Lisp、Scheme 和 Java(使用 `String.toUpperCase()`)调用的链条。 **设置需要:** SBCL、OpenLDK、Java 8 JDK(包含 `rt.jar`)和 Kawa 3.1.1 JAR。 **重要提示:** 这只是一个概念验证,*不是*一个生产就绪的实现。性能不是主要目标,目前仅支持基本数据类型。它是一次对单个 Lisp 镜像内语言边界的有趣探索。

黑客新闻 新 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 Java 在 Common Lisp 上的方案 (github.com/atgreen) 6 分,由 varjag 1 小时前发布 | 隐藏 | 过去 | 收藏 | 讨论 帮助 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系 搜索:
相关文章

原文

Common Lisp / Kawa Scheme interop via OpenLDK.

Kawa Scheme, created by Per Bothner, compiles Scheme code to Java bytecode and runs on the JVM. OpenLDK is a JVM implemented in Common Lisp; it transpiles Java bytecode to Common Lisp code. In SBCL, that Common Lisp code is then compiled to native assembly. Since both share the same SBCL process and heap, cl-kawa enables deep interoperability between Common Lisp and Scheme with no serialization or process boundaries.

Project status: technology demonstration. Not a performant or production ready implementation.

  • Evaluate Scheme from Common Lisp (strings or s-expressions).
  • Call Scheme procedures from Common Lisp.
  • Register Common Lisp functions and call them from Scheme.
  • Exchange basic values (numbers, strings, booleans, lists) across the boundary.
  • SBCL
  • OpenLDK
  • Java 8 JDK (JAVA_HOME pointing to a JRE with lib/rt.jar)
  • Kawa 3.1.1 JAR (downloaded automatically via Maven, or manually placed in libs/)
  1. Ensure prerequisites are installed and JAVA_HOME is set.
  2. Download Kawa (or let Maven fetch it) into libs/ as kawa-3.1.1.jar.
  3. Load the ASDF system from your Common Lisp image.
(asdf:load-system :cl-kawa)

;; Initialize the runtime (point to the Kawa JAR)
(kawa:startup :classpath "libs/kawa-3.1.1.jar")

;; Evaluate Scheme expressions -- as s-expressions or strings
(kawa:eval '(+ 1 2))              ; => 3
(kawa:eval '(string-length "hello")) ; => 5
(kawa:eval '(list 1 2 3))         ; => (1 2 3)
(kawa:eval "(* 6 7)")             ; => 42  (strings still work)

;; Look up a Scheme procedure and call it from CL
(let ((add (kawa:lookup "+")))
  (kawa:funcall add 10 20))        ; => 30

;; Register a CL function so Scheme can call it
(kawa:register "cl-square" (lambda (x) (* x x)))
(kawa:eval '(cl-square 7))        ; => 49

Hello World: three languages in one process

hello.lisp demonstrates the full Common Lisp → Scheme → Java interop chain in a single SBCL process:

(format t "~A~%"
  (kawa:eval '(let ((s (|java.lang.String| (string-append "Hello" ", " "World!"))))
               (|s:toUpperCase|))))
;; prints: HELLO, WORLD!

This single expression crosses three language boundaries:

  1. Common Lisp calls kawa:eval with a quoted s-expression.
  2. Kawa Scheme assembles the greeting with string-append and wraps it in a java.lang.String.
  3. Java's String.toUpperCase() runs -- its bytecode was transpiled by OpenLDK into Common Lisp, then compiled by SBCL to native x86-64 assembly.

The result flows back through Scheme's value system into Common Lisp and is printed by format. No FFI, no sockets, no serialization -- just nested function calls inside a single Lisp image.

LDK_CLASSPATH=libs/kawa-3.1.1.jar \
  JAVA_HOME=/path/to/java8/jre \
  sbcl --load hello.lisp
  • JAVA_HOME: path to a Java 8 JRE that contains lib/rt.jar.
  • LDK_CLASSPATH: optional classpath override for OpenLDK.

(kawa:startup &key classpath)

Initialize the Kawa Scheme runtime. classpath is a colon-separated string of JAR paths. Safe to call multiple times (subsequent calls are no-ops).

(kawa:eval expr &optional env) => value

Evaluate a Scheme expression. expr can be a string of Scheme source or a Common Lisp s-expression (symbols are automatically downcased, quote becomes ', t/nil become #t/'()). Returns the result converted to a Common Lisp value.

(kawa:lookup name &optional env) => object

Look up a Scheme binding by name. Returns the raw Java/Kawa object (typically a Procedure).

(kawa:funcall proc &rest args) => value

Call a Scheme procedure with Common Lisp arguments. Arguments are automatically converted to Kawa values; the result is converted back.

(kawa:register name function &optional env)

Register a Common Lisp function as a Scheme procedure. The function becomes callable from Scheme code via kawa:eval.

(kawa:scheme->cl obj) => value

Convert a Java/Kawa object to a Common Lisp value. Handles integers, floats, strings, booleans, and lists. Returns the object unchanged if no conversion applies.

(kawa:cl->scheme val) => object

Convert a Common Lisp value to a Java/Kawa object. Handles integers, floats, strings, and cons cells.

(kawa:make-environment &optional parent) => environment

Create a new Scheme environment, optionally inheriting from a parent.

Kawa type Common Lisp type
gnu.math.IntNum integer
gnu.math.DFloNum double-float
java.lang.String string
java.lang.Boolean T / NIL
gnu.lists.Pair cons
gnu.lists.LList (empty) NIL

Or manually:

LDK_CLASSPATH=libs/kawa-3.1.1.jar \
  JAVA_HOME=/path/to/java8/jre \
  sbcl --load test.lisp
  • Designed as a proof-of-concept; performance and completeness are not goals.
  • The conversion layer only handles basic scalar and list types.
  • Requires Java 8 because OpenLDK depends on rt.jar.

cl-kawa was written by Anthony Green and is distributed under the terms of the MIT license.

联系我们 contact @ memedata.com