この間iotaっぽいものを書いたけど、若干の不備があって不満だったので、改良してみることにした。
- エラー処理とか考えていない
- エラー処理はR5RSの範囲外? SRFIにエラー系の関数があるみたい。今回はパス。
- SRFI-1を参照してないので、仕様に誤りがある可能性が高い
- SRFI-1のiotaに関する説明を見たけど、内容はGaucheのリファレンスと似たような感じだった。
- オプション扱いの引数も全て書かないとNGな作りになっている
- これは何とかなりそう。
ということでオプション扱いの引数を省略できるようにしてみた。
; 再帰版 (define (iota count . args) (let ((start (if (null? args) 0 (car args))) (step (if (or (null? args) (null? (cdr args))) 1 (cadr args)))) (if (<= count 0) '() (cons start (iota (- count 1) (+ start step) step))))) ; 末尾再帰(反復)版 (define (iota count . args) (let ((start (if (null? args) 0 (car args))) (step (if (or (null? args) (null? (cdr args))) 1 (cadr args)))) (define (iota-iter count num list) (if (<= count 0) (reverse list) (iota-iter (- count 1) (+ num step) (cons num list)))) (iota-iter count start '()))) ; 末尾再帰(反復)版の trace対応バージョン ; (trace iota-iter) してからiotaを呼べばOK (define (iota-iter count start step list) (if (<= count 0) (reverse list) (iota-iter (- count 1) (+ start step) step (cons start list)))) (define (iota count . args) (let ((start (if (null? args) 0 (car args))) (step (if (or (null? args) (null? (cdr args))) 1 (cadr args)))) (iota-iter count start step '())))
何か特別な仕組みがあるのかと思っていたけど、lambdaで引数をリストとして受け取るように指定できることを利用しているらしい。