Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2011-04-09

*macroexpand-hook*でスタイルチェックの真似事

| 22:36 | *macroexpand-hook*でスタイルチェックの真似事 - わだばLisperになる を含むブックマーク はてなブックマーク - *macroexpand-hook*でスタイルチェックの真似事 - わだばLisperになる

CMUのAIリポジトリを眺めていてlint for clというものを発見しました。

面白そうなのでソースを眺めてみるに、どうやらLISPマシンには、コンパイラにstyle-checkerというものが含まれており、style-checkerにはユーザーが定義できるフックが用意されているため、これを使ってチェックさせています。

ということで、SBCLなどにもそういう層が存在してないだろうかと調べてみましたが、スタイルチェックに関しては、どうやら統一的なレイヤーのようなものはないようで、個別で警告を出しているようです。

それでは悔しいので、どうにか再現できないかと考えてみたのですが、マクロ限定となるものの *macroexpand-hook* にstyle-checkerを登録すれば似たようなことができるのではないか、と思いちょっと試してみました

(defun style-checker (expander form env)
  (awhen (get (car form) :style-checker)
    (funcall it))
  (funcall expander form env))

;; LOOPの場合 
(setf (get 'cl:loop :style-checker)
      (lambda ()
        (format *error-output*
                "~&~A: ~A~%~50:@<~A~>~%"
                'loop
                "\"I consider Loop one of the worst flaws in CL.\""
                "— Paul Graham")))

のようなものを作り、

(setq *macroexpand-hook* 'style-checker)

すると、

(defun foo ()
  (loop :for i :from 0 :to 100 :collect i))
;=> FOO
;-> LOOP: "I consider Loop one of the worst flaws in CL."
;                     — Paul Graham

という感じに文句が出ます。ちなみに警告は、*error-output*に出るので通常の結果とは混ざりません。

もっとナイスでポータブルな方法があったら是非教えて下さい!