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-02-19

LISPとリフレクション

| 02:20 | LISPとリフレクション - わだばLisperになる を含むブックマーク はてなブックマーク - LISPとリフレクション - わだばLisperになる

久々に2chのLispスレを眺めていて、3-LISPという処理系があるということを知りました。

3-LISPって一体何物と思って調べてみたら、リフレクションという概念が1982年にBrian Smith氏によって提唱された時に、その処理系として登場したとのこと。

とりあえず、面白そうだったので、処理系が公開されていないか探してみましたが、ぱっとしたものは見付からず。

それ以前にリフレクションが何だか分からなかったので、調べてみたところ、自己反映機能とも呼ばれていて、処理系自身で機能を拡張したり、実行速度を改善したりする機能のこと、とのこと。また、マクロはコンパイル時のリフレクションとも考えられる、という記述も。

何がなにやら、という感じでしたが、適当にリフレクションでヒットする論文を読んでみたところ、Common Lisp的に身近なところでは、eval-when等やコンパイル時に最適化する機構もリフレクションの一種らしいです。あと、CLOSの機能の一部とか。

例えば、define-compiler-macroはまさにそういう感じで、コンパイル時の状況によって最適化したりするのに使うようです。

(defun plus (&rest args)
  (apply #'+ args))

(define-compiler-macro plus (&whole form &rest args)
  (case (length args)
    (0 "引数がないので関数は呼び出さないで0に置き換えたいところ")
    (1 (car args))
    (t form)))

(defun foo (n)
  (plus n 3))
;=> 6

(defun bar ()
  (plus))

(print (bar))
;=> "引数がないので関数は呼び出さないで0に置き換えたいところ"

これは、CLtL2のコード例ですが、上記ではコンパイル時に引数が0か1個と判定できるならば、関数を呼びださないで、即値に置き換えてしまいます。

何となく面白いと思ったので、自分でも馬鹿っぽい例を考えてみました。

かなり無理矢理なのですが、実行結果が速く出る方を選択するdef-fasterというものを定義して、fib-slowと、fib-fastという、2種類のfibから速い方をfibという名前で呼び出せるようにする、というものです。

こういうのもリフレクションと呼べるのでしょうか…。

工夫すれば、何だか色々できそうです。

それはさておき、3-LISPがどういうものだったのか知りたい!

;; 動作
(defun fib-fast (n &optional (a1 1) (a2 0))
  (cond ((zerop n) 0)
	((< n 2) (values a1 'fast))
	('T (fib-fast (1- n) (+ a1 a2) a1))))

(defun fib-slow (n)
  (if (< n 2)
      n
      (+ (fib (1- n))
	 (fib (- n 2)))))

(def-faster fib 
    (fib-slow 30) (fib-fast 30))

(fib 10)
;=> 55, FAST

;; 定義
(defmacro run-time (fn)
  `(+ (- (get-internal-run-time)) 
      (progn
	,fn
	(get-internal-run-time))))

(defmacro def-faster (name x y)
  `(setf (symbol-function ',name)
	 (if (< (run-time ,x) (run-time ,y))
	     #',(car x)
	     #',(car y))))