Земля LISP пример избыточности?
-
14-10-2019 - |
Вопрос
Я прочитал много хороших вещей о Земля Липпа Поэтому я подумал, что могу пройти через это, чтобы увидеть, что нужно было увидеть.
(defun tweak-text (lst caps lit)
(when lst
(let ((item (car lst))
(rest (cdr lst)))
(cond
; If item = space, then call recursively starting with ret
; Then, prepend the space on to the result.
((eq item #\space) (cons item (tweak-text rest caps lit)))
; if the item is an exclamation point. Make sure that the
; next non-space is capitalized.
((member item '(#\! #\? #\.)) (cons item (tweak-text rest t lit)))
; if item = " then toggle whether we are in literal mode
((eq item #\") (tweak-text rest caps (not lit)))
; if literal mode, just add the item as is and continue
(lit (cons item (tweak-text rest nil lit)))
; if either caps or literal mode = true capitalize it?
((or caps lit) (cons (char-upcase item) (tweak-text rest nil lit)))
; otherwise lower-case it.
(t (cons (char-downcase item) (tweak-text rest nil nil)))))))
(Комментарии мои)
(К вашему сведению - подпись метода (list-of-symbols bool-whether-to-caps bool-whether-to-treat-literally)
Но автор сократил их (lst caps lit)
.)
Но в любом случае, вот вопрос:
Это имеет (cond... (lit ...) ((or caps lit) ...))
в этом. Насколько я понимаю, это приведет к if(lit){ ... } else if(caps || lit){...}
В синтаксисе стиля C. Разве утверждение не избыточно? Есть ли когда -нибудь состояние, где (or caps lit)
условие будет вызвано, если Caps nil
?
Решение
Действительно, вы правы. Увидеть ошибки для книги.
Страница 97: В Tweak-Text Function есть два сбоя, хотя она будет работать OK в большинстве реализаций LISP. Прежде всего, он использует функцию EQ для сравнения символов- символы всегда следует проверять с помощью других функций, таких как EQL или char-equal в соответствии с спецификацией ANSI. Кроме того, существует ненужная проверка (или зажженных), которые можно упростить до CAPS.
Другие советы
Я бы написал это как:
(defun tweak-text (list caps lit)
(when list
(destructuring-bind (item . rest) list
(case item
((#\space) (cons item (tweak-text rest caps lit)))
((#\! #\? #\.) (cons item (tweak-text rest t lit)))
((#\") (tweak-text rest caps (not lit)))
(otherwise (cond (lit (cons item (tweak-text rest nil lit)))
(caps (cons (char-upcase item)
(tweak-text rest nil lit)))
(t (cons (char-downcase item)
(tweak-text rest nil nil)))))))))
Заявление о случае отправляется на символ. Заявление Cond затем заботится о других условиях. Случай сравнивается с EQL. Это означает, что Case работает также для персонажей и даже может сравниться с несколькими элементами. Я также фанат стиля макета кода, который выстраивает соответствующие выражения - это полезно только с моносированными шрифтами. Это помогает мне обнаружить шаблоны визуально в коде и помогает обнаружить код, который можно упростить.
Destructuring-Bind разбирает список.
За весело, переписано с использованием цикла:
(defun tweak-text (list)
(loop with caps and lit
for item in list
when (eql item #\space)
collect item
else when (member item '(#\! #\? #\.))
collect item and do (setf caps t)
else when (eql item #\")
do (setf lit (not lit))
else when lit
collect item and do (setf caps nil)
else when caps
collect (char-upcase item) and do (setf caps nil)
else
collect (char-downcase item) and
do (setf caps nil lit nil)))