В Racket есть много встроенных процедур, которые облегчают решение проблем, связанных с манипулированием списками. Например, вы ищете for*/list
:
(define A (list string-upcase string-downcase))
(define B (list "Aa" "Bb" "Cc"))
(define done
(for*/list ([f A] [s B])
(f s)))
Он перебирает все элементы в A
, присваивая каждый из них по очереди переменной f
. И во вложенном цикле он также перебирает все элементы в B
, присваивая каждый из них по очереди переменной s
. В теле цикла он применяет каждый f
ко всем s
и собирает все в выходной список. Теперь done
содержит ожидаемые значения:
done
=> '("AA" "BB" "CC" "aa" "bb" "cc")
Если бы мы делали это вручную, используя рекурсию, было бы больше работы. Возможная реализация будет иметь процедуру для выполнения «внешнего» цикла, который будет вызывать другую процедуру для выполнения «внутреннего» цикла. Третья процедура запускает рекурсию и объединяет результаты:
(define (outer-loop funcs params)
(if (null? funcs)
'()
(cons (inner-loop (car funcs) params)
(outer-loop (cdr funcs) params))))
(define (inner-loop f params)
(if (null? params)
'()
(cons (f (car params))
(inner-loop f (cdr params)))))
(define (apply-funcs funcs params)
(apply append ; required to "flatten" the list of lists
(outer-loop funcs params)))
Мы бы использовали это так:
(define done (apply-funcs A B))
Сначала вы должны научиться решать проблемы со списком вручную, используя собственные циклы. Убедившись, что вы понимаете, что делаете, потратьте некоторое время на изучение существующих процедур списка и итераций и пониманий , идиоматического способа использования языка в реальной жизни. .