Common Lisp だと defun の中に関数を書く時は labels を使うけど、Scheme は define の中に define がネストできる。
あと、このように (if ‘() #t #f) 空リストを if で評価するとSchemeでは #t が返る!
でも、(null? ‘()) はちゃんと #t が返る。
例えばポール・グレアム氏の「On Lisp」に載ってる、ネストしたリストをフラットなリストに変換する関数、
例えば:
(flatten ‘(a (b c) d (e f)))
=> (a b c d e f)
(defun flatten (x) (labels ((rec (x acc) (cond ((null x) acc) ((atom x) (cons x acc)) (t (rec (car x) (rec (cdr x) acc)))))) (rec x nil)))
は、Gauche では、下記のように書ける。
(atom? はデフォルトで定義されてないので、関数が一個増えちゃうけど)
(define (atom? obj) (and (not (pair? obj)) (not (null? obj)))) (define (flatten x) (define (rec x acc) (cond ((null? x) acc) ((atom? x) (cons x acc)) (else (rec (car x) (rec (cdr x) acc))))) (rec x '()))
ちなみに、Common Lisp の nil はケースバイケースで ‘() に置き換えが必要な時と、素直に #f に置き換えれば済む時を見極めなくちゃいけない。
例えば上の flatten の例で、末尾の (rec x ‘()) を (rec x #f) としてしまうと、() で終わるリストではなく . #f で終わるリストになってしまう。