リストの等分割

 リストの中身をn分割したい、というような事があるが、それを実現するような関数は標準では付いてない。(slicesはそれに近いが、割り切れなかったときの挙動が欲しい物と違う。)どういう機能があれば、こういう関数を簡単に書けるのだろう?mapやfoldでは書けない気がする。(foldなら書けるような気はするが、あまり綺麗にはならないと思う。)
 結局、再帰を使って書いたのだが、コードにはあまり納得していない。

(use srfi-1)
(use util.list)
(define (list-divide lst n)
  (let* ((len (length lst))
         (a (truncate (/ len n)))
         (b (remainder len n)))
    (let loop ((rest lst) (result '()))
      (cond
       ((null? rest)
        (reverse result))
       ((> b 0)
        (dec! b)
        (loop (drop rest (+ a 1))
              (cons (take rest (+ a 1)) result)))
       (else
        (loop (drop* rest a)
              (cons (take* rest a) result)))))))
  • loopに渡す引数に、重複している部分が多すぎるが、まとめようがない。
  • 変数名にresultを使うのは良くない。restもいかがなものか。
  • (+ a 1)はどこかにまとめるべきか。2箇所なのでどうするべきか非常に迷う。
  • aとbには依存関係はないので、letの2段重ねを使えばそれで用は済むのだが、インデントが深くなるし、読みにくくなるように感じたので妥協した。
  • 末尾再帰にしてあるところだけは評価する。