Обратите внимание, что есть небольшая разница между отступов и форматирование.
Отступ обычно означает перемещение содержимого строки по горизонтали. Обычно мы уже знаем, что находится на линии и линии раньше. Если вы попросите типичный редактор указать подпункт, он не будет ничего, кроме как настроить горизонтальное положение содержимого линии. Он не будет распространять выражения по строкам.
Форматирование означает компоновку кода над одной или несколькими линиями. Lisp предоставляет красивый принтер для автоматической компоновки. Но в редакторе полный макет не очень хорошо поддерживается, тем более, что правила могут быть сложными, и довольно сложно обрабатывать комментарии и другое содержимое кода, отличного от s-expression. Макет макросов основан на простых принципах. Автоматическая компоновка для более сложных макросов, таких как LOOP, будет очень сложной.
Ваш вопрос фактически о форматирование.
(length (remove-if-not #'(lambda (card) (equal suit (suit card))) hand))
Могу ли я идентифицировать вызовы функций? Каковы аргументы? Что такое синтаксис? Как насчет длины строки? Глубина углубления?
Давайте посмотрим на вызовы функций: поместите их более заметно:
(length
(remove-if-not
#'(lambda (card)
(equal
suit
(suit card)))
hand))
Выше не выглядит так уж плохо.
Может быть, мы хотим сосредоточиться на аргументах и убедитесь, что два или более аргументов в отдельных строках:
(length (remove-if-not #'(lambda (card)
(equal suit
(suit card)))
hand))
Обычно мы хотим короткую arglists быть на одной линии, если линия не слишком долго :
(length (remove-if-not #'(lambda (card)
(equal suit (suit card)))
hand))
Выше, что я буду писать в этом случае. Структура кода достаточно ясна, и она не тратит слишком много места.
Код форматирования означает применение большого количества локальных и глобальных ограничений/правил.
Если посмотреть на выражение, мы также хотели бы написать его по-разному, потому что это вызывает много вещей, один обычно не любит:
- он считает, но он не использует функцию подсчета
- это делает ненужной работы
- создает лямбда-выражения для извлечения значения и его испытания элемента: экстракт и тест
Итак:
(count suit hand :key #'suit :test #'eql)
или просто (eql
по умолчанию):
(count suit hand :key #'suit)
Вернуться к форматированию. Мы можем сделать несколько экспериментов и посмотреть, как Лисп делает это, так как он имеет код форматировщик встроенный в (здесь Clozure Common Lisp):
? (defun test()
(dolist (*print-right-margin* '(80 60 40 30))
(format t "~%Margin: ~a" *print-right-margin*)
(pprint '(length (remove-if-not #'(lambda (card) (equal suit (suit card))) hand)))))
TEST
? (test)
Margin: 80
(LENGTH (REMOVE-IF-NOT #'(LAMBDA (CARD) (EQUAL SUIT (SUIT CARD))) HAND))
Margin: 60
(LENGTH (REMOVE-IF-NOT
#'(LAMBDA (CARD) (EQUAL SUIT (SUIT CARD)))
HAND))
Margin: 40
(LENGTH
(REMOVE-IF-NOT
#'(LAMBDA
(CARD)
(EQUAL SUIT (SUIT CARD)))
HAND))
Margin: 30
(LENGTH
(REMOVE-IF-NOT
#'(LAMBDA
(CARD)
(EQUAL
SUIT
(SUIT CARD)))
HAND))
Даже если вручную отформатированный код может выглядеть лучше во многих случаях, это полезно познакомиться с автоматическим форматированием (ака довольно печатной или «шлифовальной») и иметь возможность справиться с этим.
** setf ** не объявляет глобальные переменные. На самом деле поведение ** setf ** на необъявленных переменных является неопределенным поведением. Объявлять глобальные переменные с ** defvar ** или ** defparameter **. –
Спасибо, что указали это! Я буду следить за этим :-) –
Да, это обычная ловушка, и много уроков и т. Д., Ошибаются. Есть еще кое-что, что вы можете сделать, чтобы упростить свой код, который я обсуждал в [дополнительном ответе] (http://stackoverflow.com/a/29638261/1281433). (Тем не менее, Крис больше всего относится к отступу. Mine просто избегает необходимости в таком количестве кода.) –