Scheme で append 手続きを再定義(未完成)
append 手続きも再定義してみた。
(define list-append (lambda (a . b) (let loop ((a a) (b b)) (if (null? b) a ; b が空リストなら a を返す (if (null? a) ; b が空リストじゃなくて (loop (car b) (cdr b)) ; a が空リストなら b の car と cdr で再帰 (if (null? (car b)) ; a が空リストじゃなくて (loop a (cdr b)) ; b の car が空リストなら b の car は無視して再帰 (if (pair? (car b)) ; b の car が空リストじゃなくて (let loop2 ((x a) (y (car b))) ; b の car がペアなら (if (null? x) ; x が空リストになるまで x の最後の要素を y にくっつけつつ (loop y (cdr b)) ; y と b の cdr で再帰 (loop2 (reverse (cdr (reverse x))) (cons (car (reverse x)) y)))))))))))
いくつか用意したテストケースで、通らないものがある。
(equal? (list-append '()) '()) (equal? (list-append '() '() '()) '()) (equal? (list-append '(x)) '(x)) (equal? (list-append '(x) '(y)) '(x y)) (equal? (list-append '(x) '(y z)) '(x y z)) (equal? (list-append '(x y) '(z)) '(x y z)) (equal? (list-append '(a b) '(c d)) '(a b c d)) (equal? (list-append '(a) '(b c d)) '(a b c d)) (equal? (list-append '(a (b)) '((c))) '(a (b) (c))) (equal? (list-append '(a b) '(c . d)) '(a b c . d)) (equal? (list-append '() 'a) 'a) (equal? (list-append '(a b) 'c) '(a b . c)) ; => #f (equal? (list-append '(a b) '(c) '(d e)) '(a b c d e)) (equal? (list-append '(a b) '() '(c d)) '(a b c d)) (equal? (list-append '() '() 'c) 'c)) ; => Error
今回は、可変長引数を扱う必要があって、これにハマッてしまい、たった十数行のコードに 3 時間以上かかった(そして完成していない)。
しかも、コメントを書かないと処理がわからなくなってしまう。たぶん複雑な条件分岐には cond を使うべきだったんだと思う。