ラベル PAIP の投稿を表示しています。 すべての投稿を表示
ラベル PAIP の投稿を表示しています。 すべての投稿を表示

2010/12/27

そういえば PAIP (実用 Common Lisp) 読んだ

  • Lisp 初級者が次のレベルに向けて読む道標的なもの
  • 動的型付けの言語での開発・プログラミングのイロハ
  • Lisp 独特の柔軟性を生かした設計とインタラクティブで反復的な開発
  • Lisp でのプログラミング・開発・改善
  • Lisp の本というだけでなく、プログラミングの本
  • めちゃくちゃわかりやすい・丁寧
ザッとこんな印象。

一通り読むのに4ヶ月以上かかった。。
今年のうちに一周できてよかった。。
あと物理的に重かった。

例題や演習(解答付き)は原書のタイトル通り AI 周辺。
オブジェクトシステムや Common Lisp で書く Scheme インタプリタ & コンパイラ など(call/cc 付き)も。
(別に悪い意味ではなく、)どの辺が「実用」なのかわからなかった。


一通り読んだものの、演習はほとんど手付かず。相変わらず初級者のまま。二周目はしばらく積んでから、かな。
当たり前だけど、ちゃんと書かないと意味ない。すでに記憶が磨耗し始めてる。
なんかネガティブっぽい感想になったけど、そんなことはなく値段以上に良かった。

実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

2010/11/26

PAIP: queue

このブログでは毎月、月の日数より多く記事を書くことを軽く目標にしてきましたが、ここ2ヶ月停滞気味です。
で、気づけば次の記事で365 記事目ということで、年単位で見れば目標達成ですかね。去年は2ヶ月間まったく書かないことがあったので、320 記事でした。

PAIP も購入してから継続的に読んできて、1~11・22~25・17~18章と読みましたが、これも現在停滞気味。7~8割くらいは読んだことになりますが、例題や演習はほとんど書いてないので、むしろ「これから」といったところです。

で、結構いまさらですが、10章の queue の実装がおもしろかったので、gauche で書いてみました。cons の cdr 部に queue 本体を、car 部に queue の末尾の cons のポインタを突っ込んだ形です。この car と cdr を逆にした tconc も紹介されていますが割愛。

P.322 ~

(define (queue-contents q)
  (cdr q))

(define (make-queue)
  (rlet1 q (cons '() '())
         (set! (car q) q)))

(define (enqueue item q)
  (set! (car q)
        (rlet1 f (cons item '())
               (set! (cdr (car q)) f)))
  q)

(define (dequeue q)
  (pop! (cdr q))
  (when (null? (cdr q))
    (set! (car q) q))
  q)

(define (front q)
  (car (queue-contents q)))

(define (empty-queue? q)
  (null? (queue-contents q)))

(define (queue-append! q ls)
  (set! (cdr (car q)) ls)
  (set! (car q)
        (last-pair q))
  q)



(define q (make-queue))

(queue-contents q)
;; ()

(empty-queue? q)
;; #t

(enqueue 'a q)
;; (#0=(a) . #0#)
(enqueue 'b q)
;; (#0=(b) a . #0#)
(enqueue 'c q)
;; (#0=(c) a b . #0#)

(empty-queue? q)
;; #f

(front q)
;; a

(queue-contents q)
;; (a b c)

(queue-append! q '(d e f))
;; (#0=(f) a b c d e . #0#)

(dequeue q)
;; (#0=(f) b c d e . #0#)
(dequeue q)
;; (#0=(f) c d e . #0#)
(dequeue q)
;; (#0=(f) d e . #0#)


追記


実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

2010/10/06

Re: javascript - にも無限リストを (遅延ストリーム pipe 編)

PAIP(実用 Common Lisp (IT Architects’Archive CLASSIC MODER))に載ってる pipe は JavaScript でもいけそうだなぁと思って書いてみました。わりと強引に書きました。JavaScript には Lisp/Scheme のマクロのように引数の評価を遅らせるような機能(?)がないので、しかたなく呼び出し側で無名関数で包みました。よくないスタイルですが、取りあえず動くので良いんじゃないでしょうか。他に何か良い方法があれば、教えていただけると助かります。

で、その pipe でエラトステネスの篩をやってみると以下のような感じです。
var primes = sieve(integers(2));
enumerate(primes, 10);
// ->  [2,3,5,7,11,13,17,19,23,29,31,function () { return filter(pred, tail(pipe));}]

JavaScript による pipe とエラトステネスの篩のソースは以下のもの。JavaScript っぽさとかないかもしれませんし、突っ込みどころも多々あるでしょうが多めに見てください。。


階乗のリストだとこうでしょうか。
function facts (pipe) {
  var rec = function (p, acc){
    var h = head(p);
    var cur = 0 === h ? 1 : h * acc;
    return makePipe(cur, function () { return rec(tail(p), cur); });
  };
  return rec(pipe, 1);
}

enumerate(facts(integers(0)), 5);
// -> [1,1,2,6,24,120,function () { return rec(tail(p), cur); }]

enumerate(facts(integers(0)), 10);
// [1,1,2,6,24,120,720,5040,40320,362880,3628800,function () { return rec(tail(p), cur); }

ところで

JavaScript の生みの親であるブレンダン・アイクが、実は
ブラウザで動く Scheme が作れると聞いて!
ということでネスケに入ったなんて話もあるらしいですね。
伝統的なマクロじゃないにしろ、それっぽいものがあったら JavaScript ももっと強力だったでしょうに。

そういえば

Rhino だと Scheme 由来の継続(continuation)や let が使えるそうで。
Scheme 以外で明示的に継続に触れたことが無いので、試して見ます。
(ruby にも call/cc があるんでしたっけ)

例えば、何の変哲もない、というかただ再帰するだけの deep 関数を例に取ると、
function deep (n){
  var ret;
  if (n === 0){
    ret = n;
  } else {
    ret =  deep(n - 1);
  }
  print(n);
  return ret;
}
deep(10);
/*
0
1
2
3
4
5
6
7
8
9
10
0
*/

再帰の基底条件に達した後は、今まで潜った再帰を戻るわけですよね。そのときに n が print されている状態です。
で、継続のお決まりの例である脱出をしてみたいので、以下のように書き換えて見ます。

ポイントは、実際の再帰を内部で定義した rec 関数に任せている点と、deep の先頭で継続オブジェクトを取得している点。
function deep (n){
  var cont = new Continuation();
  var rec = function (n){
    var ret;
    if (n === 0){
      ret = n;
      cont(ret);
    } else {
      ret =  rec(n - 1);
    }
    print(n);
    return ret;
  };
  return rec(n);
}

deep(10);
// -> 0
print されませんね。結果である 0 だけが表示されています。この結果が意図通りのものです。

基底条件に達した時点で保存しておいた継続に結果を渡して呼び出しているので、潜った再帰はなかったことに。なかったことに、と言うと語弊があるでしょうか。まぁ、気になったら Scheme でもやってみてください。

一応確認するために、rec の下で print すると、ちゃんと再帰していることがわかります。基底条件、つまり最深部まで再帰を潜って cont に渡された値が cont が宣言された以降の処理の結果となるわけです。何を言ってるかわから(ry。
function deep (n){
  var cont = new Continuation();
  var rec = function (n){
    print(n);
    var ret;
    if (n === 0){
      ret = n;
      cont(ret);
    } else {
      ret =  rec(n - 1);
    }
    print(n);
    return ret;
  };
  return rec(n);
}
deep(10);
/*
10
9
8
7
6
5
4
3
2
1
0
0
 */

追記

あ、今回使った JavaScript の処理系は
Rhino 1.7 release 2 2009 03 22
です。

Emacs + Rhino + js2.el + js-comint.el 最強です。

追記2

いつも教えて頂いてます!ありがとうございます!
@valvallow ジェネレータが実装されてない処理系も多いみたいですね。 とりあえず、無限リストとかの考え方は無視して典型的な JavaScript らしい書き方で書いてみました。 http://gist.github.com/613523


実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

2010/09/22

`',hoge は `(quote ,hoge)

実用 Common Lisp (IT Architects’Archive CLASSIC MODER) P.272
イディオム「`',fn-names」はコメントする価値がある。最初は混乱するかもしれないが、よく使用されるイディオムである。等価な形式 `(quote ,fn-names) のほうが、理解しやすいかもしれない。
これはわかりやすい。

実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

PAIP の pipe でエラトステネスの篩(ふるい)

実用 Common Lisp (IT Architects’Archive CLASSIC MODER) 9.3 P.263 ~。
遅延評価による無限集合の例。遅延リストとしてのpipe。Scheme(Gauche)で書いたこともあり、コードは書籍とは若干違います。

pipe を用いたエラトステネスの篩。


delay と force による pipe


クロージャによる pipe



実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

2010/09/10

PAIP: メモ化, memo, memoize, define-memo

メモ化。以前もいくつかいい加減な記事を書いています。。


メモ化については On Lisp や SICP(計算機プログラムの構造と解釈)なんかでも出てきますね。

今回はPAIP(実用 Common Lisp (IT Architects’Archive CLASSIC MODER))P.253 第3部 第9章 9.1 より。Common Lisp ではなく Gauche(Scheme)で書いてあるので、コードが多少違います。

以下コード。一つ目がmemo関数のプロトタイプで二つ目が本番 memo, meomize, define-memo, clear-memoize。都合により clear-memo も追加しています。

本番。



実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

2010/08/28

PAIP tree-search

実用 Common Lisp 6.4 ~
探索ツール。9LISP で紹介のため、取りあえずUP。gauche で書いてあります。
tree-search

深さ優先

幅優先

最良優先探索

ビーム探索


実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

2010/08/27

PAIP debug, dbg, dbug-indent

実用 Common Lisp の P.116 にあるデバッグ用のツールです。
すごく便利だったので、gauche で書いて使えるようにしてみました。

library の lib なら liv じゃなくて lib でしょう。valvallow の library ということで liv でいいかな、などと。

実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

2010/08/08

PAIP 3.1 「let*式と等価なlambda式を示せ」をマクロで・・・

掲題の通りの問題です。今さら手書きするのもあれなので、マクロ書いてエキスパンドすれば良いんじゃね?と思ってマクロ書きましたが、思ったよりエキスパンドしてくれませんでした・・・。


実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

PAIP Excersise 2.4

ほとんどさっき書いたやつでワロタ


実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

PAIP 2.6

どうもうまいこと書けない。。それに名前付けがいつも悪い。

読むペースと書くペースが合わない。。どんどん先を読んで、後から書いて、2度読むことになってなんとも。。だがそれがいい。

実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

2010/08/05

PAIP 2.2 でちょっとしたマクロ

PAIP(実用 Common Lisp (IT Architects’Archive CLASSIC MODER))の当該箇所の本題とは無関係なのですが、マクロを書いたので晒しておきます。

以下コード。一番上が書籍に載っているもの。2, 3番目がマクロ。

私は On LispLET OVER LAMBDA Edition 1.0 も読んだわけですが、"読んだ"だけで書けるようになったわけではありません。どうやら。書かないと書けるようにはならないでしょうね。両書籍も書きながら再読しないといけませんね。

ちなみに書籍は Common Lisp ですが、今のところ Scheme(Gauche)で書いています。
この分厚い書籍を携帯したり、電車の中で読むには勇気が要りますね。。今日から実行していますが。。

実用 Common Lisp (IT Architects’Archive CLASSIC MODER)