Пример:
Как преобразовать список:
'(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
В список списков:
'((0 1 2 3) (4 5 6 7) (8 9 10 11) (12 13 14 15))
На основании ответов, предоставленных до сих пор, я пришел к следующему:
Сначала определите функцию, которая принимает до 'n' элементов от начала списка:
(define (take-up-to n xs)
(define (iter xs n taken)
(cond
[(or (zero? n) (empty? xs)) (reverse taken)]
[else (iter (cdr xs) (- n 1) (cons (car xs) taken))]))
(iter xs n '()))
Вторая аналогичная функция для остальной части списка:
(define (drop-up-to n xs)
(define (iter xs n taken)
(cond
[(or (zero? n) (empty? xs)) xs]
[else (iter (cdr xs) (- n 1) (cons (car xs) taken))]))
(iter xs n '()))
Это можно было бы сделать как одну функцию, которая возвращает два значения, а Racket имеет функция split-at, которая дает тот же результат, но я сделал это в качестве упражнения.
пс. Правильно ли это использование хвостовой рекурсии?
Тогда разбиение на блоки можно записать так:
(define (split-into-chunks n xs)
(if (null? xs)
'()
(let ((first-chunk (take-up-to n xs))
(rest-of-list (drop-up-to n xs)))
(cons first-chunk (split-into-chunks n rest-of-list)))))
pps. Можно ли улучшить его еще больше или он «достаточно хорош»?