autoloadが何をしているかを赤裸々に

autoloadが何をしているかと言うのを調べたら合点がいくという話だったので早速見てみた。ついでに、自分が適当に読むときに何をしているかも露出プ(ry。公開*1
■8割り方間違ったlispの読み方を一緒にしてみるツアー
 まずは、autoloadを調べるのだから、何処に関数が書かれているかチェック。前はこういうときに毎回Grepで検索していたわけだけど、xyzzyにはタグジャンプと言う機能があるので、学習した最近では無駄にそれを使っている。時々調子に乗って飛びすぎて酷いことになるが、それはいいとして、タグジャンプの使い方はxyzzyWikiとかにあるので任せて、設定してある自分としては*scratch*とかにautoloadと打ち込んで、文字の上でF4キーを押すと勝手に関数の所にジャンプしてくれて楽チンな訳ですよ。で、出てくる関数がこんなの。

(defun autoload (fn file &optional commandp macrop)
  (unless (fboundp fn)
    (eval (cond (macrop
		 `(defmacro ,fn (&rest args)
		    (load-and-go ',fn ,file nil t args)))
		(commandp
		 `(defun ,fn (&rest args)
		    (ed:interactive "P\np")
		    (load-and-go ',fn ,file (ed:interactive-p) nil args)))
		(t
		 `(defun ,fn (&rest args)
		    (load-and-go ',fn ,file nil nil args)))))))

何となく眺めた所、load-and-goというよく分からない関数に引数を渡しているだけの様子。他には、(unless (fboundp fn)〜なので(autoload 'shell "shell" t)のshellが既に読み込まれてシンボルになっている場合は動作しないようにしてる感じかなぁとかくらい。自分がソースとやらを読むときは正直言って余り読めていないので、読んでいるというより眺めている幹事。細かいとこは華麗にスルーというか意味が分からないので無視。分からんもんは分からんのです。偉い人にはそれが分からんのです。で、肝心の中身load-and-goが何をしているのか分からないので、すかさずF4でload-and-goにタグジャンプ。タグジャンプがアレな人はGrep

(defun load-and-go (fn file interactive-p macrop args)
  (let ((ofn (symbol-function fn)))
    (si:*load-library file)
    (when (eq ofn (symbol-function fn))
      (error "オートロードが失敗しました"))
    (cond (macrop
	   (macroexpand (cons fn args)))
	  (interactive-p
	   (ed::autoload-complex-command fn (car args) (cadr args)))
	  (t
	   (apply fn args)))))

で、出てきたload-and-goはこんな感じだった。引数は(autoload 'shell "shell" t)で云えば、shellと"shell"とtなのでその辺に脳内で適当に置き換え。これは忘れないうちに、何か具体例と変換しておかないとメモリ不足義みの脳みその持ち主としては厳しいので、適当に脳内で具体例に変換。つまり。

(autoload 'shell "shell" t)なら
load-and-go (fn file interactive-p macrop args)は
fn : shell
file : "shell"
interactive-p : t

load-and-goの中身を眺めることにして、letは何しているかよく分からんから細かいことは華麗にスルー。多分、fn=shellの中身をofnに入れ込んだのかな。良く知らんが結論的にはfn=ofn=shellと。si:*load-libraryは何しているか知らないけど、load-libraryと大差ないだろうと、多分file="shell"を読み込み。(when (eq ofn (symbol-function fn))っていうのもイマイチ何をしているのか分からないけど、何となく前後関係からすればload-libraryする前と後でfnが変化していないならってことかな?変化していないんだからshellは読み込めていないつまり失敗だろうと。云う感じでエラーを吐いていると妄想。次はcondでダラダラ並んで終了。condは実質ifなので、ifでmacropとinteractive-pとtを調べて条件が一致した奴を実行する感じ。ed::autoload-complex-command は意味が分からんが何かしら関数を実行する手段なんだろうと勝手に推測。というのも、(t以下がapplyしてfnを実行しているような雰囲気だから。ちなみにこういうときのapplyの意味が分からんと思ったらapplyにカーソルをあわせてF1を押すとヘルプが出てくるという素敵な機能がinfo-modoki-modeとかにあるので、それも入れておくのがいい感じ。之によって何も覚えてなくても何も知らなくても適当にF1とF4を押し捲ることで、何となく意味が分かるという、素敵な言語lisp。いやlispが素敵なんじゃなくてxyzzyが素敵なのかもしれない。

で、これを読んで何が分かったかと言うと、ダンプファイルがとかバイトコンパイルがとか、そんな話は一切出てこないし、単にファイルを読んで中に書かれているだろうと思われる関数を実行しているような感じ。つまり、ダンプファイルの読み込みするときの順番の方はstartup.lにだけなので気にしなくていいのかなと勝手に思った。(あくまで勝手に思っただけだから信用してはいけない。)

■ついでに、8割り方間違ったlispの読み方をまとめると

  1. 見知らぬ文字列が出てきたら兎に角F1を連打する
  2. 色が付いていない見知らぬ関数らしきものが出てきたらF4を兎に角連打する。
  3. 出てきた説明の意味じゃよく分からないときは其の関数をGrepして他でどういう風に使っているか調べる。
  4. 引数とかがやたらと長く続く場合は今知りたい具体的な中身に勝手に置き換える。
  5. 分からない所は無視して次に分かりそうなところを読む
  6. それでも分からない所は見なかったことにする。

この6つを守ることで誰でも確実にlispを読んだような気になれるよ。たとえ読めなくても見なかったことにすればいいしね。すべて解決。出来なかったときのアフターケアまで考えられてて、我ながら完璧だな。( ̄ー+ ̄)キラリ

*1:スーパー適当にlispらしきものを書いたり、読んだりしている様子を公開しているのは低脳ぶりを赤裸々に露出するのが趣味だとかマゾだとか、そういうわけじゃないです。ええ、断じて違うのです。どうせ誰も見てないだろとかいう崇高な適当精神によっ(以下略