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 で終わるリストになってしまう。
 
 
 

§1101 · Posted By · 5月 12, 2013 · Development · Tags: , , · [Print]