ryos36の日記 (Scheme Switch)

2008-01-03

mkf は必要なく

23:11

結局 apply の common lisp 版は簡単に出来た。

(defun apply-in-underlying-common-lisp (pproc args)
  (apply pproc args))

scheme と変わらないじゃん。まぁとにかく common lisp への移植は半分終わった。いやいや大物が残っているぞ。

if, begin, cond か。

日記じゃなくてちゃんと資料としてまとめておこう。SICP を読み解く

書いていると SICP の後光でえらくなた気分になって、なんか不遜な文章になっている、、、まぁいいか。

どうでもいいけど vi に ecl を移植している人がいるのね。ecl はコンパクトであるとうたっているが、、、どうだろう?

common lisp 版とりあえず完成

00:03

かなり雑だけど common lisp 版完成。適当に動くが、、、primitive が足りないので相当不便。eq なんて実現するのが大変そうだぞ。むしろ C で書いたほうが楽。(なにをもって”むしろ”なのかは不明)

2008-01-01

苦労の末

18:09

与えられた、引数のリストと関数のリストから関数を返す関数 mkf 。

(setf a '(a b))
(setf af '(+ a b))
(defun mkf (a0 a1) (eval `(function (lambda ,a0 ,a1))))
;(defmacro mkf (a0 a1) `(function (lambda (a b) ,a1)))
;(setq f #'(mkf a af))

(setq rf (function (lambda (x y) (+ x y))))
(format t "~a~%" rf)
(format t "~a~%"
        (apply rf '(1 2)))

;(setq f (eval (mkf a af)))
(setq f (mkf a af))
(format t "~a~%" f)
(format t "~a~%"
        (apply f '(1 2)))

しかしクロージャまで渡せない、、、、my-apply なるものを作る必要があるのか?

;これはエラー
;(let ((x 4))
;  (let ((f (mkf '(a b) '(* (+ a b) x))))
;    (apply f '(4 5))))

2007-12-30

lisp, scheme の比較

15:34

ちょっと気になり簡単なプログラムをリスプ処理系で計算してみた。

(setf x 12345678901234567890)
(* x x)

acl(alisp), clisp, cmucl,mit-scheme は合格。gosh は誤差が出る。vx-scheme は double になってしまう。う~む。

scheme 処理系の中身

15:34

どのように内部表現をしているか気になったので軽く調べてみた。

vx-scheme

4byte x 4 が基本の組み合わせ(cellの構造)。最初の8byte が car部で、続く8バイトが cdr部。最初の8バイトの内訳は 4byte が ID で、続く 4Byte が値あるいはポインタ

mit-scheme

どうやら上位何ビットかをIDに分けている模様。

Gauche

最初に共通のヘッダがある

SICP のこと全然書いてないじゃん

15:34

SICPインタプリタは apply をどうしているか?結局、

(define apply-in-underlying-scheme apply)

としており、本当の意味で(何が本当かはわからんが、、、)インタプリタじゃないな。例えば、これを lisp で実装しようと思えば簡単に出来るかもしれない。しかし、C で実装しようと思うと、結局この部分は考えないといかん(当たり前)。勿論、apply-in-underlying-scheme という名前でわかるように評価部分を抜き出しているので、ここを真剣に考えればいい”だけ”のはなしなのかもしれないが、、、

vx-scheme はどうなっているのかを調査予定。

common-lispSICP の (Yet Another Implementation Of)

ちょっとかいた set! と変数の評価は出来た。

この間 read も lisp処理系に依存していることに気がついた。

; set nocindent
; set lisp
; set showmatch
(defvar *debug-flag* nil)
(defmacro debug-trace (&body body)
        `(if (not (null *debug-flag*)) (progn
                                         ,@body)))

(defmacro do-test-case (&body body)
  `(let ((func #'(lambda () (progn
                              ,@body
                              ))))
     (debug-trace (funcall func))))

(defun self-evaluating? (exp)
  (cond ((numberp exp) t)
        ((stringp exp) t)
        (t nil)))

(defun variable? (exp) (symbolp exp))

(defun tagged-list? (exp tag)
  (if (consp exp)
    (eq (car exp) tag)
    nil))

(defun quoted? (exp)
  (tagged-list? exp 'quote))

(defun first-frame (env) (car env))
(defun frame-variables (frame) (car frame))
(defun frame-values (frame) (cdr frame))
(defun enclosing-environment (env) (cdr env))

(setf the-empty-environment nil)

(defun set-variable-value! (var val env)
  (labels ((env-loop (env)
                     (debug-trace (format t "env-loop ~a~%" env))
                     (if (eq env the-empty-environment)
                       (error "Unbound variable" var)
                       (let ((frame (first-frame env)))
                         (scan (frame-variables frame) (frame-values frame) env ))))
           (scan (vars vals env)
                 (debug-trace (format t "scan ~a ~a~%" vars vals))
                 (cond ((null vars)
                        (env-loop (enclosing-environment env)))
                       ((eq var (car vars))
                        (setf (car vals) val))
                       (t (scan (cdr vars) (cdr vals) env)))))
    (env-loop env)))

; test-case
(do-test-case
  (setf my-env '(((a b c) 1 2 3) ((a e f g) 4 5 6 7) the-empty-environment))
  (format t "first-frame ~a~%" (first-frame my-env))
  (set-variable-value! 'a 129 my-env)
  (format t "my-env ~A~%" my-env)
  (set-variable-value! 'f 1103 my-env)
  (format t "my-env ~A~%" my-env))

;(defun eval-assignment (exp evn)
;------------------------------------------------------
(defun lookup-variable-value (var env)
  (labels ((env-loop (env)
                     (debug-trace (format t "env-loop ~a~%" env))
                     (if (eq env the-empty-environment)
                       (error "Unbound variable" var)
                       (let ((frame (first-frame env)))
                         (scan (frame-variables frame) (frame-values frame) env ))))
           (scan (vars vals env)
                 (debug-trace (format t "scan ~a ~a~%" vars vals))
                 (cond ((null vars)
                        (env-loop (enclosing-environment env)))
                       ((eq var (car vars))
                        (car vals))
                       (t (scan (cdr vars) (cdr vals) env)))))
    (env-loop env)))
;------------------------------------------------------
(defun assignment-variable (exp) (cadr exp))
(defun assignment-value (exp) (caddr exp))

(defun eval-assignment (exp env)
  (set-variable-value! (assignment-variable exp)
                       (scheme-eval (assignment-value exp) env)
                       env)
  'ok)

(defun assignment? (exp) (tagged-list? exp 'set!))

(setf *debug-flag* t)
(do-test-case
  (defun scheme-eval (exp env)
    (format t "scheme-eval ~a ~a~%" exp env)
    (format t "S scheme-eval ~a ~%" (self-evaluating? exp))
    (format t "A scheme-eval ~a ~%" (assignment? exp))
    (cond ((self-evaluating? exp) exp)
          ((assignment? exp) (eval-assignment exp env))
          ;((variable? exp) (format t "variable ~a~%" env))
          ((variable? exp) (lookup-variable-value exp env))
          (t (format t "Unknown expression"))))
  (setf my-env '(((a b c) 1 2 3) ((a x f g) 4 5 6 7) nil))
  (scheme-eval '(set! x 4) my-env)
  (format t "my-env ~a~%" my-env)
  (setf x-value (scheme-eval 'x my-env))
  (format t "x-value ~a~%" x-value)
)

ポールグレハム的にはダメプログラムだろうな。set-variable-value! と lookup-variable-value は殆ど同じ関数だ。

ついでに書くと環境は次のとおりになる。

 (setf my-env '(((a b c) 1 2 3) ((a e f g) 4 5 6 7) nil))

非対称になるのが気になる。(a b c) (1 2 3) でしょ。common lisp 的にはハッシュを使うか (:a 1 :b 2 :c 3) というところか。

2007-12-20とりあえず MIT-Scheme のコンパイル

OSFreeBSD 6.1。

ports からインストールしようとしたら X11 で躓いた。とりあえず動くのが欲しいのだが、、、X11 とかインストールしたいくない(サーバだし)。ports を眺めていたらどうやら、MIT Schemeインストールには MIT Schemeバイナリが必要なようだ。まず、バイナリインストールして、それからソースをコンパイルするようだ。きっと、Schemeコンパイルscheme が必要なんだろう(確信なし)。

まず、卵になる mit-schemeインストールmit-scheme-7.7.1-ix86-freebsd.tar.gz。これをまず自分のホームの install というディレクトリを作って展開。

次に、最新ソースを MIT からダウンロードして、configure --without-X --prefix=/home/ryos/istrnstall としてから make 。なぜか strlen の宣言でエラーになったので、uxio.c に #include <string.h> を追加。う~ん。怪しい。あとはうまくコンパイルできた。 X11 なしの mit-scheme の出来上がり。

今、良く見ると usrdef.c とか bchdef.c とかある。なんかしらんが、C のソースを生成している。

SICP のソースも検索エンジンからダウンロードして、、、ちゃんと動く。まったくソースを書かずに(あるいは写さずに)全部動いちゃう。これじゃ勉強にならない(苦笑)。

組み込みシステムと scheme

16:20

scheme は組み込みシステム向けにいいと思うのだが(common lisp じゃでか過ぎる)ネームスペースがないのが困る。どっかにマクロが書けないから scheme はだめだと(http://cl-www.msi.co.jp/solutions/knowledge/lisp-world/articles/scheme)いう意見もある。

これからは scheme + C++ で組み込みシステムの世界をわたっていこうとおもっていて、そう宣言して CEATEC に展示してみた。わかりづらいけど、scheme の絵

http://image.itmedia.co.jp/l/im/mobile/articles/0710/04/l_yo_mf17.jpg

地味だな。CEATEC に出したんだけど scheme という文字がちょこっと見える。誰も反応してくれないや。そういえば、vm-scheme の作者は今 google につとめているんだよね。

http://code.google.com/p/vmscheme/

Google Code だって、、う~ん。Google にすべてが集まってしまうのには本当に危機感を感じてしまう。