SICP:問題2.17
とても久しぶりにSICPの問題をやってみた。前回の問題から飛んでいるけど(一応間の問題も解いてはある)、今回初めて使ってみたGaucheの単体テストでの確認が便利だったので、思わず先に書いてしまった。
問題 2.17
与えられた(空でない)リストの最後の要素だけからなるリストを返す手続き
last-pair
を定義せよ:(last-pair (list 23 72 149 34)) (34)
length
と同じようにリスト全体の cdr
ダウンで。Schemeの組み込みライブラリに同名の手続きが入っているので、my-last-pair
という名前にした。
(define (my-last-pair items) (if (null? (cdr items)) items (my-last-pair (cdr items))))
gauche.testを使ったテスト
ところで、今まではテストを手でやっていたのだけど、試すときに使っていたGaucheに単体テストのライブラリgauche.testが含まれていることを知り、今回初めて使ってみた。
上の手続きをex-2-17.scmというファイルに入れ、以下の内容のex-2-17-test.scmというファイルを作った。
;; 問題2.17のテスト (use gauche.test) (test-start "問題2.17") (load "./ex-2-17.scm") (test "要素数1の場合" (list 1) (lambda () (my-last-pair (list 1)))) (test "問題文の例" (list 34) (lambda () (my-last-pair (list 23 72 149 34)))) (test-end :exit-on-failure #t)
実行すると以下のように出力され、テストが成功したことが分かる。
$ gosh ex-2-17-test.scm Testing 問題2.17 ... test 要素数1の場合, expects (1) ==> ok test 問題文の例, expects (34) ==> ok passed.
テストが失敗するように、わざと以下のテストケースを入れるとどうなるか。
(test "絶対失敗する!" (list 23) (lambda () (my-last-pair (list 23 72 149 34))))
出力はこのようになり、失敗した場合の結果が分かりやすく表示された。
$ gosh ex-2-17-test.scm Testing 問題2.17 ... test 要素数1の場合, expects (1) ==> ok test 問題文の例, expects (34) ==> ok test 絶対失敗する!, expects (23) ==> ERROR: GOT (34) failed. discrepancies found. Errors are: test 絶対失敗する!: expects (23) => got (34)
かなり便利なので、今後答えがはっきりと決まる問題を解くときには、積極的に使っていきたい。