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 |

2007-04-13

CADRでSICP Exercise 3.1

| 22:38 | CADRでSICP Exercise 3.1 - わだばLisperになる を含むブックマーク はてなブックマーク - CADRでSICP Exercise 3.1 - わだばLisperになる

CADRでSICP Exercise 3.1.に挑戦 - Structure and Interpretation of Computer Programs

挑戦しているL-99も段々問題が難しくなり、また、

Prologの問題をLispで解こうというだけになかなか一筋

縄では行かず、若干煮詰り気味な感じ。

そこで、計算機プログラムの構造と解釈(通称SICP)にも

挑戦してみることに。

一捻りして、LispMで回答を作成することにしてみた。

使用するLispM環境は、CADRのエミュレータ。

1977〜1984位までは、最先端のLisp環境だった模様。

CADRのLispの処理系は、Maclisp系のLisp Machine Lisp

(Zetalispの前身)。

Schemeや、Common Lispと違うところは、レキシカルス

コープではないところ。でも、クロージャを作成する機

構は存在し、Common Lispにかなり近いので、なんとか

なるだろうと。

ということで、今回は、Exercise 3.1に挑戦。次回から

Exercise 1.1から順番に回答を作成予定。

お題:局所状態変数の実現(?)
(define A (make-accumulator) 5)

(A 10)
=> 15

(A 20)
=> 25
を実現するmake-accumulatorを作成せよ。
解答
;; Lisp Machine Lisp
(defun make-accumulator (init)
  (let-closed ((acc init))
    #'(lambda (n)
	(setq acc (+ acc n)))))

;; Scheme
(define (make-accumulator init)
  (let ((acc init))
    (lambda (n)
      (set! acc (+ acc n)))))

面白いところ:

Lisp Machine Lispはダイナミックスコープなので、ク

ロージャを作成するには、それ用の関数等を使うらしい。

主な関数は、そのものずばりな名前のclosure。

let-closedは、マクロで使い勝手的には、Common Lisp

や、Schemeのletと同じ感じ。詳細は、

マニュアル参照

クロージャを操作する関数が色々あり、クロージャの中

身の変数の状態とか覗いてみれたり、変更できたりする。

(setq A (make-accumulator 5.))
(funcall A 10.)
=> 15.

(closure-variables A)
=> acc

(closure-function A)
=> (lambda (n) (setq acc **))

(closure-bindings a)
=> CADRでは未実装?

(closure-alist A)
=> ((acc . 15))

(symeval-in-closure A 'acc)
=> 15

(set-in-closure A 'acc 100.)
=> 100.

(funcall A 10.)
=> 110.

(boundp-in-closure a 'acc)
=> CADRでは未実装?

(locate-in-closure a 'acc)
->#<DTP-LOCATIVE 222343434>

(makeunbound-in-closure a 'acc)
=> CADRでは未実装?

(copy-closure a)
=> CADRでは未実装?

L-99 (73)

| 16:25 | L-99 (73) - わだばLisperになる を含むブックマーク はてなブックマーク - L-99 (73) - わだばLisperになる

L-99 P73に挑戦 - L-99:Ninety-Nine Lisp Problems

P72の問題に挑戦してみたけれど、問題の意図が分から

なかったので、飛してP73に挑戦。

お題は、多分岐ツリーをLisp的なリスト表現にする関数

の作成と、その逆変換をする関数の作成。

問題が進むにつれ、段々解答が正しいのか分からなくなっ

てきた。テストケースとかちゃんと書かないと駄目なの

かもしれない。

P73

解答
;; Common Lisp
(defun multiway-tree->lispy-token-list (tree)
  (cond	((atom tree) tree)
	((= 1 (length tree)) (car tree))
	('T `(,(multiway-tree->lispy-token-list (car tree))
	      ,@(mapcar #'multiway-tree->lispy-token-list
			(cdr tree))))))

(defun lispy-token-list->multiway-tree (tree)
  (labels ((frob (tree depth)
	     (cond ((and (zerop depth) (atom tree)) `(,tree))
		   ((atom tree) tree)
		   ('T `(,(frob (car tree) (1+ depth))
			  ,@(mapcar #'(lambda (n) 
					(if (atom n) 
					    `(,n) 
					    (frob n (1+ depth))))
				    (cdr tree)))))))
    (frob tree 0)))

;; Scheme 
(define (multiway-tree->lispy-token-list tree)
  (cond ((not (pair? tree)) tree)
	((= 1 (length tree)) (car tree))
	(else `(,(multiway-tree->lispy-token-list (car tree))
		,@(map multiway-tree->lispy-token-list
		       (cdr tree))))))

(define (lispy-token-list->multiway-tree tree)
  (let frob ((tree tree) 
	     (depth 0))
    (cond ((and (zero? depth) (not (pair? tree))) 
	   `(,tree))
	  ((not (pair? tree)) 
	   tree)
	  (else 
	   `(,(frob (car tree) (+ depth 1))
	     ,@(map (lambda (n) 
		      (if (pair? n) 
			  (frob n (+ depth 1))
			  `(,n)))
		    (cdr tree)))))))