※追記あり
Scheme では繰り返しを再帰で実現する。じゃ、n 回の繰り返しはこう書けばいいだろうか。
(define hello (lambda (n) (let loop ((m n)) (if (= m 0) #t (begin (print "Hello!") (loop (- m 1))))))) (define main (lambda (args) (hello (string->number (cadr args)))))
このスクリプトは、引数の回数だけ “Hello!” を繰り返し出力する。
^o^ > gosh hello-loop.scm 3 Hello! Hello! Hello!
確かに n 回の繰り返しを行っていて、目的は達成している。けど、気になるのは hello 関数の返り値だ。ここでは便宜的に(というか苦し紛れに)#t を返しているけど、なんだか気持ちが悪い気がする。Scheme 的にはどうなんだろうか。
[追記]
Kei さんからコメントをもらった。返り値が要らないなら when か unless を使えばいいとのこと(未定義値が返ってくる)。
gosh> (define (hello n) (let loop ((i 0)) (unless (= i n) (print "Hello!") (loop (+ i 1))))) hello gosh> (hello 3) Hello! Hello! Hello! #<undef>
確かに #<undef> が返ってきている。この方がしっくりくるな。when を使うとこうかな。
gosh> (define (hello n) (let loop ((i 0)) (when (< i n) (print "Hello!") (loop (+ i 1))))) hello gosh> (hello 3) Hello! Hello! Hello! #<undef>
なるほど。うん、unless と when を覚えた。Kei さんありがとうございます。
と、ここまで書いといて何だけど、そもそも print を繰り返すこと自体が Scheme 的じゃない気がしてきた。なのでこう書き直してみた。
(define hello (lambda (n) (let loop ((m n) (ls '())) (if (= m 0) ls (loop (- m 1) (cons "Hello!" ls)))))) (define main (lambda (args) (for-each print (hello (string->number (cadr args))))))
hello 関数が返すのは “Hello!” のリストで、それを main 関数のほうで出力している。
^o^ > gosh hello-loop2.scm 3 Hello! Hello! Hello!
良くなった。