(define (fact n) (if (= n 0) 1 (* n (fact (- n 1)))))考量到 C 語言的關鍵字,我們「模仿」成以下的風格: (factorial.c)
define(int, factorial, (int n), if(eq(n, 0), 1, mul(n, factorial(sub(n, 1))))) define(int, main, (void), (printf("10! = %d\n", factorial(10)), EXIT_SUCCESS))由上可見,「形式」上,保有括號與原子 (atom) 的呈現,不過,這就不是 C 語言了呀?沒關係,只要在編譯器那邊動點手腳即可,以下是編撰的 Makefile 內容:
CFLAGS = -Wall \ -D'define(ret, name, args, block) = ret name args { return block; }' \ -D'if(expr, block1, block2) = expr ? block1 : block2' \ -D'eq(a, b) = a == b' \ -D'sub(a, b) = a - b' \ -D'mul(a, b) = a * b' \ -include "stdio.h" -include "stdlib.h" TARGET=factorial all: gcc -o $(TARGET) $(TARGET).c $(CFLAGS) clean: rm -f $(TARGET)編譯並執行:
$ make >/dev/null && ./factorial 10! = 3628800結果符合我們預期。由上述 macro 定義 (即 -D'name(args...)=definition' 的那五行),特意將 Scheme 語法的 atom 轉變成 C 語言的語法,原本 Scheme 的語法是:
define(型別 函數名稱 (引數串列), (函數 ...))做了小量的挪移,恰好符合。同樣地,以上僅示範「模擬」語法的可能性,實際尚須考量到 Scheme/Lisp 在處理運算,本質上採用 prefix (前序運算式) 的設計。
太巧妙了哈哈
由 td 發表於 August 2, 2008 10:40 AM