Общий стиль для комментариев на Лиспе
- Четыре точки с запятой для комментариев к целому подразделу файла.
- Три точки с запятой для введения одной процедуры.
- Две точки с запятой для описания определения выражения / процедуры в следующей строке.
- Одна точка с запятой для последнего комментария.
Комментарии к обзору процедуры, вероятно, должны соответствовать стилю документов RnRS, поэтому просто добавление комментариев к вашей процедуре как есть, будет выглядеть примерно так:
;;; Procedure: display-n NUM ...
;; Output each argument to the screen in the order they are provided.
(define
display-n (lambda nums
(letrec ((display-n-inner (lambda (nums)
(display (car nums))
(if (not (equal? (cdr nums) '()))
(display-n-inner (cdr nums))))))
(display-n-inner nums))))
N.B. Я не использую три точки с запятой для всего описания процедуры, так как в Emacs он запутывает заполнение абзаца.
Теперь о коде, я бы отбросил всю вещь define-variable-as-a-lambda. Да, я понимаю, что это «самый чистый» способ определения функции, и он обеспечивает хорошую согласованность с определениями процедур, являющимися результатами LET и других процедур, но есть причина для синтаксического сахара, и это должно сделать вещи более удобочитаемый. То же самое для LETREC - просто используйте внутренний DEFINE, что то же самое, но более читабельно.
Нет ничего особенного в том, что параметр DISPLAY-N-INNER называется NUMS, поскольку процедура такая короткая, и DISPLAY-N в любом случае просто передает свои NUMS прямо ему. "DISPLAY-N-INNER" - своего рода неубедительное имя. Вы могли бы дать ему что-то с более семантическим значением или дать ему простое имя, например, "ITER" или "LOOP".
Теперь о логике процедуры. Во-первых, (equal? (cdr nums) '())
глупо и лучше, чем (null? (cdr nums))
. На самом деле, когда вы работаете со всем списком, лучше всего сделать базовый вариант проверкой того, является ли сам список, а не его CDR, пустым. Таким образом, процедура не выдаст ошибку, если вы передадите ей аргументы без аргументов (если только вы не хотите, чтобы это делалось, но я думаю, что для DISPLAY-N имеет смысл ничего не делать , если она ничего не получает). Кроме того, вы должны проверить, следует ли остановить процедуру, а не продолжать ли:
(define (display-n . nums)
(define (iter nums)
(if (null? nums)
#t ; It doesn't matter what it returns.
(begin (display (car nums))
(iter (cdr nums)))))
(iter nums))
Но при всем этом я бы сказал, что сама процедура - не лучший способ выполнить задачу, которую она выполняет, поскольку она слишком связана с деталями обхода списка. Вместо этого вы должны использовать более абстрактный метод FOR-EACH для выполнения работы.
(define (display-n . nums)
(for-each display nums))
Таким образом, вместо того, чтобы читать информацию о процедурах, попадающих в детали CAR и CDR, он может просто понять, что FOR-EACH будет отображать каждый элемент NUMS.