#:g1: lisp-criticの紹介

Posted 2014-06-25 15:30:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の177日目です。

lisp-criticとはなにか

 lisp-criticは、Christopher K. Riesbeck氏作のCommon Lispのコードを批評してくれるユーティリティです。
ノースウェスタン大学のコンピュータ科学のコース EECS 325 AI Programming での学習用のツールとして開発されたようです。

パッケージ情報

パッケージ名lisp-critic
Quicklisp×
プロジェクトサイトExercise Checking Tools

インストール方法

 Quicklispに収録されてるかなと思って検索してみたところ、どうもまだ収録されていないようなので、上記プロジェクトサイトから必要な物をダウンロードしてセットアップします。
必要なものをまとめてgithubに置いてみているので良かったらどうぞ

Quicklispのlocal-projects等に置けば、Quicklispでロードできます。

(ql:quickload :lisp-critic)

試してみる

 3年前にも紹介してみましたが、その時は、SLIMEの*slime-repl*バッファに出力するようにしてみました。
以来、この3年間使い続けてみましたが、全くといって良い程無視してしまっています。
もうちょっと目立つなら、少しは読むようになるかもということで、デスクトップ通知でもさせてみることにします。

デスクトップ通知 + SLIME + lisp-critic

 SLIME(Emacs)側は、

(defadvice slime-compile-defun (before critique-advice activate)
  (slime-eval `(swank::lisp-critic ,(slime-defun-at-point) :timeout 5000)))

のように slime-compile-defun に advice を付けて、Common Lisp側では、

(defun ?::notify-send (title mesg &key (timeout 10)
                                 (icon "lisplogo_alien_256.png")
                                 (urgency :normal))
  (*:run-program "notify-send"
                 (list "-u" (string-downcase urgency)
                       "-t" (princ-to-string timeout)
                       "-i" icon
                       "--"
                       title
                       mesg)
                 :search T))

(defun swank::lisp-critic (string &key (timeout 1000)) (let ((mesgs (with-output-to-string (*standard-output*) (lisp-critic:critique-definition (read-from-string string))))) (dolist (m (remove "" (*:split "\\s*-{10,}\\s*" mesgs) :test #'string=)) (?:notify-send "Lisp Critic" m :timeout timeout))) nil)

のような感じでデスクトップ通知にメッセージを投げます。
REPLに出力する為に整形したものを更に切り出している所が無駄ですが、これ以上は、lisp-criticの中身をいじることになりそうなので、とりあえず今回はこれで良しとします。

 動作イメージとしては、こんなコードをコンパイルすると…

(defun foo ()
  (defun bar ()
    (setq a 'b)))
lisp-critic

みたいに批評されます。
結構表示がウザいですが、これなら読むようになるかも。

批評をカスタマイズする

 批評は、lisp-rules.lisp の中で定義されていますが、define-lisp-patternというもので定義します。
こんな感じに

(define-lisp-pattern copy-array
    (copy-array (?))
  "There is no COPY-ARRAY in Standard Common Lisp. You have to create ~
   an empty array and fill it as needed.")

拾いたいパタンと、メッセージを定義してやればOKです。

関連

まとめ

 今回は、lisp-criticを紹介してみました。
Common Lisp製のツールをカスタマイズして使うこと自体Common Lispの良い勉強になると思うので、こういったツールを整備してみるのもなかなか良いのではないでしょうか。

comments powered by Disqus