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-26

CADRでSICP 1.6

| 21:37 | CADRでSICP 1.6 - わだばLisperになる を含むブックマーク はてなブックマーク - CADRでSICP 1.6 - わだばLisperになる

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

Exercise 1.6
ifが特殊形式である必要性について

(defun new-if (predicate then-clause else-clause)
  (cond (predicate then-clause)
	(T else-clause)))
のように新しいifを定義する。
これが、
(defun sqrt-iter (guess x)
  (new-if (good-enough-p guess x)
          guess
	  (sqrt-iter (improve guess x)
	             x)))
のように使われた場合、どのように動くかを考察せよ、
というような問題。
解答
特殊形式でないと、then部、else部ともに評価を終えた
後で、分岐を評価しようとするので、自分を呼び出す再
帰が使われている場合、無限ループになってしまう。
そして全然質問とは関係ないが、ずっと解答と書いてい
たつもりが、回答となっていたことにはたと気付いたの
で全部直した。

自分のための理解補助コード:
(defun foo (x)
  (if (zerop x)
      'zero!
    (princ "foo!")))

(foo 0)
-> ZERO!

(defun bar (x)
  (new-if (zerop x)
	  'zero!
	  (princ "foo!")))

(bar 0)
->ZERO!
と共にfoo!もプリントされる。

2007-04-25

CADRでSICP 1.5

| 20:03 | CADRでSICP 1.5 - わだばLisperになる を含むブックマーク はてなブックマーク - CADRでSICP 1.5 - わだばLisperになる

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

Exercise 1.5
(defun p ()
  (p))

(defun test (x y)
  (if (= x 0)
      0
    (if (functionp y)
	(funcall y)
      y)))
とした場合、
(test 0 #'p)
の評価が正規順序の評価と、作用的順序の評価でどう違っ
てくるかを説明せよ。
解答
正規順序だと、(p)が実行されることになるので、無限
ループになるんではなかろうか。ということで、(p)の
評価が終らず結果が出せない。
ちなみにCADRでは、PDL Overflowになる。
作用的順序だと、(p)は評価する必要がないので0が返さ
れ終了する。

CADRでSICP 1.4

| 20:01 | CADRでSICP 1.4 - わだばLisperになる を含むブックマーク はてなブックマーク - CADRでSICP 1.4 - わだばLisperになる

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

Exercise 1.4
演算子が合成式でも評価モデルが使えるかを観察せよ。
Scheme:
(define (a-plus-abs-b a b)
  ((if (> b 0) + -) a b))

解答
Lisp Machine Lispというか、Lisp-2だと
(defun a-plus-abs-b (a b)
  (funcall (if (> b 0) #'+ #'-) a b))
となると思う。
(a-plus-abs-b 3 -3)
-> 6.
にはなるけど、これは演算子が合成式ってことになりま
せんわよね。

CADRでSICP 1.3

| 00:15 | CADRでSICP 1.3 - わだばLisperになる を含むブックマーク はてなブックマーク - CADRでSICP 1.3 - わだばLisperになる

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

Exercise 1.3
3つの数のうち、大きい方2つの自乗の和を返す手続きを
つくれ。
解答
(defun sum-square-largest-2 (x y z)
  (if (and (<= x y) (<= x z))
      (+ (* y y) (* z z))
    (sum-square-largest-2 y z x)))

(defun sum-square-largest-2 (x y z)
  (cond ((and (<= x y) (<= x z))
	 (+ (* y y) (* z z)))
	((and (<= y z) (<= y z))
	 (+ (* z z) (* x x)))
	((and (<= z x) (<= z y))
	 (+ (* x x) (* y y)))))

偶々回答の前にJoe Marshall氏の小ネタ(日本語訳)を見てしまったため、

逆に普通の答え方の方がややこしく感じられるという罠。

(defun min-of-3 (x y z)
  (if (and (<= x y) (<= x z))
      x
    (min-of-3 y z x)))

の変形として捉えたってことなのかしらん。


CADRでSICP 1.2

| 00:13 | CADRでSICP 1.2 - わだばLisperになる を含むブックマーク はてなブックマーク - CADRでSICP 1.2 - わだばLisperになる

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

Exercise 1.2
(5 + 4 + (2 - (3 - (6 + 4/ 5))))/ (3 * (6 - 2) * (2 - 7))
を前置記法で書け。
解答
(// (+ 5 4 (- 2 (- 3 (+ 6 (// 4 5)))))
    (* 3 (- 6 2) (- 2 7)))

//となっているのは、Maclisp〜LISP Machine LISP〜

Zetalispでは、/はエスケープ文字となっているため。

ちなみに(// 4 5)の結果は、0.となる。

2007-04-19

CADRでSICP Exercise 1.1

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

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

今回から1.1から順にSICPの問題に挑戦。

Exercise 1.1
インタプリタに式を入力して結果を観察。
10
-> 10.

(+ 5 3 4)
-> 12.

(- 9 1)
-> 8.

(+ (* 2 4) (- 4 6))
-> 6.

(defvar a 3)
-> NIL

(defvar b (+ a 1))
-> NIL

(= a b)
-> NIL

(if (and (> b a) (< b (* a b)))
    b
  a)
-> 4.

(cond ((= a 4) 6)
      ((= b 4) (+ 6 7 a))
      ('T 25))
-> 16.

(* (cond ((> a b) a)
	 ((< a b) b)
	 ('T -1))
   (+ a 1))
-> 16.

Lisp Machine Lisp固有と思われるところ:

・defvarが値をセットした時にNILを返すところ。

Maclispもそうなのかと思って試してみたら、Maclispは、

変数名を返す。Gaucheでも、SBCLでもそう。この辺は、

言語仕様なのか、処理系依存なのか調べないと分からな

い…けど…まあ…良いか(´▽`*)

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では未実装?