Yet Another Common Lisp Problems #6 drop
再開。
ホームページ移転のお知らせ - Yahoo!ジオシティーズ●問題6
リスト xs の先頭から n 個の要素を取り除く関数 drop xs n を定義してください。なお、Common Lisp には同等の機能を持つ関数 nthcdr があります。
> (drop '(a b c d e) 3) (d e) > (drop '(a b c d e) 0) (a b c d e) > (drop '(a b c d e) 6) ()
;; 再帰で (defun drop (xs n) (if (<= n 0) xs (drop (cdr xs) (1- n)))) => drop (test-drop) drop: 3 assertions passed, 0 failed. ;; do で (defun drop (xs n) (do ((xs xs (cdr xs)) (n n (1- n))) ((<= n 0) xs))) => drop (test-drop) drop: 3 assertions passed, 0 failed. ;; loop で (require "cmu_loop") => t (defun drop (xs n) (loop repeat n for x on xs finally (return x))) => drop (test-drop) drop: 3 assertions passed, 0 failed.
答え合わせ
ホームページ移転のお知らせ - Yahoo!ジオシティーズ●解答6
リスト : リストの先頭から n 個の要素を削除する (defun drop (ls n) (if (or (<= n 0) (null ls)) ls (drop (cdr ls) (1- n)))) ; 別解 (defun drop1 (ls n) (do ((n n (1- n)) (ls ls (cdr ls))) ((or (<= n 0) (null ls)) ls)))drop は簡単です。引数 n が 0 以下または引数 ls が空リストになるまで drop を再帰呼び出しするだけです。別解は do による繰り返しバージョンです。
ls が nil になったらそこで止めていいのに気付いてなかった。
余談: lisp-unit を使ってみた
(require "lisp-unit") => t (use-package :lisp-unit) => t (define-test drop (assert-equal '(d e) (drop '(a b c d e) 3)) (assert-equal '(a b c d e) (drop '(a b c d e) 0)) (assert-equal '() (drop '(a b c d e) 6))) => drop (defun test-drop () (let ((*trace-output* *standard-output*)) (run-tests 'drop))) => test-drop (test-drop) drop: 関数が定義されていません: drop ;; ちゃんと定義して... (test-drop) drop: 3 assertions passed, 0 failed.