Lisp 擁有 50 年歷史,孕育了 if-then-else、垃圾回收、詞法閉包等現代語言核心特性。其獨特的 S 表達式(括號密集語法)與宏系統賦予「可編程的程式語言」能力,極適合元編程與 DSL 構建。JVM 上主流實現包括:
下載 kawa-1.9.1.jar 加入類路徑,運行 java kawa.repl 進入 REPL(Read-Eval-Print-Loop):
#|kawa:1|# (+ 1 2)
3
#|kawa:2|# (* (+ 1 2) (- 3 4))
-3
#|kawa:3|# (if (> (string-length "Hello world") 5) (display "Longer than 5 characters"))
Longer than 5 characters
前綴表示法、巢狀結構、動態類型,體現 Lisp 簡潔核心。
(define (add a b) (+ a b)) ; 定義函數
(add 1 2) ; => 3
(define (double a) (* a 2))
(define numbers (list 1 2 3))
(map double numbers) ; => (2 4 6) 高階函數 map
; Lambda 匿名函數
(map (lambda (a) (* 2 a)) numbers) ; => (2 4 6)
; 閉包
(define (make-adder a) (lambda (b) (+ a b)))
(define add-3 (make-adder 3))
(add-3 2) ; => 5 閉包捕獲 a=3
宏在編譯期展開,可延遲求值、引入新語法:
; 定義 dotimes 循環宏
(define-syntax dotimes
(syntax-rules ()
((dotimes count command)
(do ((i 0 (+ i 1)))
((= i count) #t)
command))))
(dotimes 5 (display "Print this ")) ; 展開為 do 循環並執行
import kawa.standard.Scheme;
public class SwingExample {
public void run() {
InputStream is = getClass().getResourceAsStream("/swing-app.scm");
new Scheme().eval(new InputStreamReader(is));
}
}
(define-namespace JFrame)
(define-namespace JButton)
(define frame (make JFrame))
(define button (make JButton "Click only once"))
(define action-listener
(object (ActionListener)
((action-performed e :: ActionEvent) ::
(*:set-enabled button #f)))) ; 禁用按鈕
(*:set-default-close-operation frame (JFrame:.EXIT_ON_CLOSE))
(*:add-action-listener button action-listener)
(*:add frame button)
(*:pack frame)
(*:set-visible frame #t)
define-namespace 簡化 Java 類引用(如 import)。make 實例化 Java 物件,自動轉換參數類型。*: 前綴調用實例方法(駝峰轉連字符)。:: 型別標註輔助編譯器實現 Java 介面。Class:.FIELD 訪問靜態欄位。JVM 上的 Lisp(以 Kawa 為例)提供 REPL 互動開發、強大宏系統、無縫 Java 互操作,適合構建 DSL、規則引擎、動態業務邏輯等場景。Clojure 則以現代並發原語與更優雅的 Java 整合成為新寵,值得持續關注。