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 |

2008-07-05

defun-compile-time

| 23:07 | defun-compile-time - わだばLisperになる を含むブックマーク はてなブックマーク - defun-compile-time - わだばLisperになる

先日yharaさんのブログで、Edi Weitz氏のマクロ入門の記事が取り上げられていました。

黒帯マクロ使いを目指す皆様はソースに目を通してみるといいんじゃないでしょうか。
とりあえずscreamer.lsp のdefun-compile-timeの大群が恐ろしいです。

というdefun-compile-timeについての言及があったのですが、自分は、このマクロ入門のネタで勉強会を開催しておきながら、Screamerのソースは眺めもしていなかったのでdefun-compile-timeも知りませんでした(笑)

ということで、ちょっと追っ掛けてみることにしました。

  • インストール
(asdf-install:install "http://archive.ubuntu.com/ubuntu/pool/universe/c/cl-screamer/cl-screamer_3.24.2.orig.tar.gz")

cliki経由のインストールは失敗してしまうようなので、直にファイルを指定してインストールしてみました。

  • 中身を探る

インストールはできたので、ソースを眺めてみることにします。

defun-compile-timeの定義は、

(defmacro defun-compile-time (function-name lambda-list &body body)
 `(eval-when (:compile-toplevel :load-toplevel :execute)
   (cl:defun ,function-name ,lambda-list ,@body)
   #-(or akcl harlequin-common-lisp)
   (eval-when (:compile-toplevel) (compile ',function-name))))

のようになっているようです。

akclや、harlequin-common-lispの記述になんとく時代を感じさせます。ちなみにsbclもコンパイルされるので、この2つの仲間に入れても良いのかもしれません。

それで、このマクロが解決しようとしている問題ですが、

(defpackage :eval-when-test 
  (:use :cl))

(defmacro defun-compile-time (function-name lambda-list &body body)
 `(eval-when (:compile-toplevel :load-toplevel :execute)
   (cl:defun ,function-name ,lambda-list ,@body)
   #-(or akcl harlequin-common-lisp sbcl)
   (eval-when (:compile-toplevel) (compile ',function-name))))

(defun my-car (list)
  (car list))

(defmacro eval-when-test-ng (&rest args)
  `(list ,(my-car args)))

(defun-compile-time my-car2 (list)
  (car list))

(defmacro eval-when-test (&rest args)
  `(list ,(my-car2 args)))


(eval-when-test '(1 2 3 4))

(eval-when-test-ng '(1 2 3 4))

のようなeval-when-test.lispというファイルを作ったとします。

eval-when-test、eval-when-test-ngはマクロなのですが、このマクロが使うヘルパー関数として、my-carとmy-car2が同じファイルで定義されています。また、定義したマクロは、同じファイル中で早速使っているという状況です。

eval-when-testが使うヘルパー関数は、はdefun-compile-timeで定義。

eval-when-test-ngが使うヘルパー関数は、は普通にdefunで定義。

それで、

(compile-file "/u/mc/lisp/Work/eval-when-test")
(load "/u/mc/lisp/Work/eval-when-test.fasl")

のようにコンパイル→ロードと実行するのですが、通常のdefunでは、コンパイル時に関数の評価まではされないので、eval-when-test-ngは、内部で使用しているmy-carが未定義となり上手く動かないという問題が発生します。

これを回避するためには、コンパイル時に評価もされるように、eval-whenで包むことになるのですが、これを便利にするマクロだったようです。

これと同じ問題は、defvar、defstructにもあるので、兄弟マクロとして、defvar-compile-time、defstruct-compile-timeが同居していました。

なるほど、なるほど。

他にも便利そうなマクロが隠れていそうです。

7/5 第6回 慢性的CL勉強会@Lingr 8時だョ!全員集合まとめ

| 22:31 | 7/5 第6回 慢性的CL勉強会@Lingr 8時だョ!全員集合まとめ - わだばLisperになる を含むブックマーク はてなブックマーク - 7/5 第6回 慢性的CL勉強会@Lingr 8時だョ!全員集合まとめ - わだばLisperになる

昨日、7/5 20:00から4回目の勉強会を開催させて頂きました!

発言して頂いた方約6名、observer(ROM)の約方8、9名で、大体14名前後を推移しつつでした。

今回は、CLの落し穴で1時間半でした。

反省と課題

  • 良くも悪くも、なんとなくまったりしていた。
ログ:
  1. Common Lispの落し穴集
  2. http://www.lingr.com/room/gKpArxPn9wi/archives/2008/07/05#msg-41636737

謝辞

勉強会の告知をして頂き、その上、なんとロゴを作って頂いたようです!

ありがとうございます!!

今回も勉強会の一員に加えて頂いてありがとうございます!

次回…。

7/12日 20時から開催します!

お題は、未確定ですが何か面白そうなものを物色しております。

何か、アイディア/要望等ありましたら、Lingrに書き置きでもしてみて下さい!。

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20080705