Spec z #lisp-pl "sprzedał" mi dziś ciekawą sztuczkę w Common Lispie. Język ten dysponuje tylko jednym formalnym rodzajem dwoma rodzajami komentarza - komentarzem "do końca linii", zaczynającym się od znaku ;, na przykład:
(defun swap-buffers ()
(let ((temp *ca-front-buffer*))
(setq *ca-front-buffer* *ca-back-buffer*)
(setq *ca-back-buffer* temp)))
oraz komentarzem blokowym*, na przykład:
Jednakże kod Lispu zwykle nie jest, w przeciwieństwie do rodziny ALGOLa, formatowany liniowo. Powiedzmy, że chcielibyśmy wykomentować ostatnią instrukcję z powyższego przykładu:
(defun swap-buffers ()
(let ((temp *ca-front-buffer*))
(setq *ca-front-buffer* *ca-back-buffer*)
Zauważmy, że uszkodziliśmy strukturę kodu - zarówno let
jak i defun
są teraz niedomknięte. Ten drobny niuans utrudnia wygodną pracę z kodem.
W powyższej sytuacji zależało nam na wykomentowaniu pojedynczego S-wyrażenia, a nie pojedynczej linii. Byłoby więc wspaniale, gdyby dało się myśleć na poziomie S-wyrażeń, a nie linii kodu. I faktycznie, możemy to zrobić, a sztuczka polega na użyciu swego rodzaju warunkowej kompilacji języka Lisp:
(defun swap-buffers ()
(let ((temp *ca-front-buffer*))
(setq *ca-front-buffer* *ca-back-buffer*)
#+nil(setq *ca-back-buffer* temp)))
#+nil to instrukcja warunkowego obliczania, która sprawi, że S-wyrażenie, do którego przylega, nigdy nie zostanie obliczone. W praktyce jest to odpowiednik wykomentowywania kodu w C/C++ za pomocą preprocesora (#if 0
/ #endif
).
Dzisiaj tyle :).
Przypisy
* - ten sposób komentowania odkryłem przypadkiem, przeglądając kod algorytmu, który wygrał ostatnie Google AI Challenge.