Решение dyoo является хорошим и лаконичным в такой Схеме, как Racket, в которую встроены полезные итерационные подпрограммы. Однако, к вашему сведению, ваш 'outputListData' недалеко от стандартного рекурсивного способа сделать это. Вам просто нужно изменить пару строк:
(define (outputListData list)
(cond
[(null? list) #f] ; actually doesn't really matter what we return
[else (printf "~s\n" (first list)) ; display the first item ...
(outputListData (rest list))])) ; and start over with the rest
Поскольку это «императивная» процедура, которая не предназначена для возврата значения, на самом деле не имеет значения, что мы делаем с пустым списком, пока мы прекращаем повторяться (чтобы избежать бесконечного цикла). Если список не пустой, мы выводим первый элемент и начинаем рекурсивно с остальной частью списка.
Кстати, вот еще один способ, которым вы могли бы написать что-то почти идентичное, если бы вам просто нужен был цикл for в середине какой-то другой функции:
(let loop ((l (list 'foo 'bar 'baz 'quux))) ; or put whatever input you need
(cond ((null? l) #f)
(else
(printf "~s\n" (first l))
(loop (rest l)))))
Один из способов думать об этом «именованном let» заключается в том, что он определяет временную функцию с именем loop
, которая работает так же, как outputListData
выше. Схема обладает хорошим свойством, заключающимся в том, что она не будет наращивать стек для таких «хвостовых вызовов», как эти, поэтому вы всегда можете написать то, что будет «итеративным» циклом for
или while
в этом рекурсивном стиле.
Я настоятельно рекомендую Little Schemer Фридмана и Феллайзена для быстрого знакомства с этим стилем написания функций! Я нашел это на странице Дугласа Крокфорда здесь .