Подтвердить что ты не робот

Правильный комментарий для функционального программирования

Я изучаю схему, и я просто понял, что я действительно не знаю, как правильно прокомментировать код моей функциональной схемы. Я знаю, как добавить комментарий, конечно - добавьте ; и поместите свой комментарий после него. Мой вопрос в том, что я должен поместить в свои комментарии, и где я должен комментировать максимальную удобочитаемость и понятность для других программистов, читающих мой код?

Вот фрагмент кода, который я написал. Это функция, называемая display-n. Он может вызываться с любым количеством аргументов и выводит каждый аргумент на экран в том порядке, в котором они предоставляются.

(define display-n
  (lambda nums
    (letrec ((display-n-inner 
              (lambda (nums)
                (display (car nums))
                (if (not (equal? (cdr nums) (quote ()))
                    (display-n-inner (cdr nums))))))
      (display-n-inner nums))))

Изменить: улучшена табуляция и заменена '() на (quote ()), чтобы избежать неправильного использования форматирования.

Я просто не знаю, как и где добавлять комментарии, чтобы сделать его более понятным. Некоторый код схемы, который я видел, просто имеет комментарии наверху, что отлично, если вы хотите использовать код, но не полезно, если хотите понять/изменить его.

Также - как мне прокомментировать макросы?

4b9b3361

Ответ 1

Общий стиль комментариев Lisp -

  • Четыре точки с запятой для комментариев по целому подразделению файла.
  • Три точки с запятой для введения одной процедуры.
  • Две точки с запятой для описания определения выражения/процедуры в следующей строке.
  • Одна точка с запятой для комментариев в конце строки.

Комментарии к обзору процедур, вероятно, должны соответствовать стилю RnRS documens, поэтому просто добавлять комментарии к вашей процедуре как есть, будет выглядеть примерно как

;;; 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.

Ответ 2

Некоторые случайные примечания:

  • Традиционно код Scheme и Lisp использовал ;;; для комментариев toplevel, ;; для комментариев в коде и ; для комментариев в той же строке, что и код, который они комментируют, Emacs поддерживает это, рассматривая каждую из них немного по-другому. Но особенно на стороне Scheme это уже не так популярно, но разница между ;; и ; по-прежнему распространена.

  • Большинство современных схем приняли новые виды комментариев: theres:

    • #|...|# для комментария блока - полезно для длинных фрагментов текста, которые комментируют весь файл.
    • #;<expr> - это комментарий, который заставляет реализацию игнорировать выражение, которое полезно для отладки.
  • Что касается фактического содержания того, что писать, что не отличается от любого другого языка, за исключением того, что с более функциональным подходом у вас обычно больше вариантов, как выложить свой код. Это также упрощает запись меньших функций, которые объединены в более крупные функциональные возможности, и это также меняет стиль документации, поскольку многие такие небольшие функции будут "самодокументироваться" (в том смысле, что их легко читать и очень очевидно, как они работают).

  • Мне не нравится звучать как сломанная запись, но я все же думаю, что вы должны провести некоторое время с HtDP. Одна вещь, которую он рекомендует в своем рецепте дизайна, - сначала написать примеры, затем документацию, а затем расширить ее до фактического кода. Кроме того, этот рецепт оставляет вам код с очень стандартным набором комментариев: типы ввода/вывода, назначение цели, документацию о том, как функция выполняется при необходимости, а примеры можно рассматривать как другую документацию ( который превратился бы в прокомментированный код в "реальном" коде). (Есть другие книги, которые занимают аналогичную позицию по документации.)

  • Наконец, документирование макросов не отличается от документирования любого другого кода. Единственное, что может отличаться от того, что написано в комментариях: вместо описания того, что делает какая-то функция, вы склонны описывать, какой код он также расширяет, поэтому комментарии также больше на мета уровне. Общий подход к макросам заключается в минимальной работе внутри макроса - только то, что необходимо на этом уровне (например, выражение переноса в (lambda () ...)), и оставить фактическую реализацию функции. Это также помогает в документировании, поскольку две связанные части будут содержать комментарии о том, как макрос расширяется и как он выполняется независимо.

Ответ 3

Я следую подходу, подобному тому, что размещено здесь:

http://www.cc.gatech.edu/computing/classes/cs2360/ghall/style/commenting.html

Примечание: это для Common Lisp.

В частности:

" Four Semicolons(;;;;)
...denote a sub heading in the file...

Three Semicolons(;;;)
...denote a description of the succeeding function, macro, or
variable definition...
[I usually just most of the description into the "docstring"
  of the function or variable.] 


 Two Semicolons(;;)
 ...denote a description of the succeeding expression...

 One Semicolon(;)
 ...denotes an in-line comment that explains a particular element
    of the expression on that line... Brevity is important for
    inline comments"

Ответ 4

Я думаю, что отличным местом для начала было бы поставить ваше описание с одним предложением о том, что делает функция

Он может вызываться с любым количеством аргументов и выводит каждый аргумент на экран в том порядке, в котором они предоставляются.

в качестве комментария в начале.

Я не особенно разбираюсь в схеме, поэтому я не могу комментировать (:-) о том, ожидаются ли дополнительные пояснительные комментарии, объясняющие механику того, как функция достигает этого результата в соответствии с обычным стилем схемы ( но я не подозреваю).