(define (term-expander n val partial)
(if (zero? n)
partial
(term-expander (- n 1) val (cons val partial))))
(define (append-expand a b)
(if (pair? b)
(append a (term-expander (car b) (cadr b) '()))
(append a (list b))))
(define (expand l) (foldl append-expand l '() ))
> (expand '(a (3 b) (3 a) b (2 c) (3 a)))
(a b b b a a a b c c a a a)
Итак ... term-expander
занимает (5 a)
-> '(a a a a a)'
.append-expand
добавит новый термин (расширенный, если это пара) к нашему ответу в процессе.просто нужно свернуть это по списку.
Я надеюсь, что у вас уже есть foldl
, но вот мое на всякий случай.
(define (foldl op seq init)
(define (iter acc rest)
(if (null? rest)
acc
(iter (op acc (car rest)) (cdr rest))))
(iter init seq))
РЕДАКТИРОВАТЬ
Поняв, что потом это можно сделать немного более естественно с foldr
, а не foldl
(потребуется append-expand
, написанный иначе).Почему вы не видите, можете ли вы найти это?В основном та же идея, но она будет работать со списком «спереди назад» и более естественным образом подойдет для cons
структур
Вот я делаю это без сгиба, но это работает так же, и я недействительно заботьтесь об этом
(define (term-expander p partial)
(if (zero? (car p))
partial
(term-expander (cons (- (car p) 1) (cdr p)) (cons (cadr p) partial))))
(define (expand l)
(define (expand-rec l partial)
(if (null? l)
partial
(let ((t
(if (pair? (car l))
(term-expander (car l) '())
(list (car l)))))
(expand-rec (cdr l) (append partial t)))))
(expand-rec l '()))
> (expand '(a (3 b) (3 a) b (2 c) (3 a)))
(a b bb a a a b c c a a a)
Если вы предпочитаете, секция (if (pair?...
может вместо этого перейти к term-expander
, и тогда вы просто позвоните через доску.Я немного предпочитаю этот способ, но все равно