#+のちょっといい話

Lispでは式1個だけをコメントアウトしたいことがよくあります。

(list A B C)

このようなプログラムで、Bをコメントアウトするときに、
行コメントをつかうと非常に不格好になります。

(list A ;B
  C)

ブロックコメントコメント #| … |# を使えばもう少し奇麗に書けますが、面倒です。

(list A #|B|# C)

Schemeの場合、R6RSで式コメントが書けるようになりました。

(list A #;B C)

非常に簡潔です。素晴らしい。

Common Lispで同じことをする場合、#+を使います。
#+はCで言うところの#ifdefであり、環境に依存するコードを書くときによく使います。

(defun do-something-quickly()
  #+allegro ACL専用の処理
  #+sbcl SBCL専用の処理
  #+clisp CLISP専用の処理
  #-(and allegro sbcl clisp) (error "Use ACL, SBCL or CLISP.")
)

#+X Yと書くと、(member X *features*)が真であれば、Yがリードされ、
偽であればYは読み飛ばされます。
*feature*に含まれないシンボルXをわざと書けば、式コメントが実現できます。

;; 例1
(list A #+nil B C)
;; 例2
(list A #+ignore B C)
;; 例3
(list A #+comment B C)

多くの場合、上の3つの例はうまく動いてくれますが、
万が一、*feature*にnilやignoreやcommentが含まれている場合、Bがコメントアウトされません。

どうしたものかと思いつつ、ずっと #+nil を使い続けていたんですが、
どんな環境でも確実にうまくいく方法を見つけました。

(list A #+(or)B C)

#+(or)です。
#+(or X Y …) Zと書くと、
(or (member X *features*) (member Y *features*) …)
が真のときのみ、Zがリードされます。
つまり、orに引数を与えなければZは常にリードされません。
これで、*features*にnilが含まれていないか心配で眠れない夜ともおさらばです。

Leave a Reply