Scheme 入門 7.繰り返しから、練習問題5。
リストの要素の順番を反転させる関数
(define my-reverse-do (lambda (ls) (do ((l1 ls (cdr l1)) (l2 '() (cons (car l1) l2))) ((null? l1) l2)))) (print (my-reverse-do '(1 2 3 4 5)))
takatoh@nightschool $ gosh my-reverse-do.scm (5 4 3 2 1)
数のリストの要素の合計を求める関数
(define sum-do (lambda (ls) (do ((l ls (cdr l)) (s 0 (+ s (car l)))) ((null? l) s)))) (print (sum-do '(1 2 3 4 5)))
takatoh@nightschool $ gosh sum-do.scm 15
正の整数を表す文字列を整数に変関する関数
(define string->integer-do (lambda (str) (do ((l (string->list str) (cdr l)) (i 0 (+ (- (char->integer (car l)) 48) (* i 10)))) ((null? l) i)))) (print (string->integer-do "12345"))
takatoh@nightschool $ gosh string-to-integer-do.scm 12345
[追記]
do 構文について補足。このあいだは do 構文の体裁を↓こう書いたけど
(do ((変数 初期値 ステップ)) (終了条件) 本体)
より正しくはこう。
(do ((変数 初期値 ステップ) ...) (終了条件 式) 本体)
まず、変数は複数定義できる。それから、終了条件の後に式を書くと、式を評価した値が do 構文の値になる。でもって、本体は必要がなければ省略ができる。
上の3つの例ではどれもそうなっている。
Gauche のユーザリファレンスには次のような例が出ている。
(do ((i 0 (+ i 1)) (j 0 (+ i j))) ((= i 10) j) (print j))
この例では、i と j の2つの変数を使って、最終的には j を返している。そして毎回のループごとに本体 (print j) を実行している。
gosh> (do ((i 0 (+ i 1)) (j 0 (+ i j))) ((= i 10) j) (print j)) 0 0 1 3 6 10 15 21 28 36 45
これを見ると、値を得るには終了条件の後の式を使って、本体は副作用に使うのがいいのかも。