2010/08/30

ポール・グレアムがオススメする本

ベンチャーの起業家に私たちが推薦しているのはデール・カーネギーの「人を動かす」。仕事をする人は必ず読むべき本だ。1960年代より前の版を入手してほしい。 カーネギーの死後、本は委員会に「改訂」され続け、その結果かえって悪くなってしまった。
有名な本ですね。読んでいません。個人的に「うさんくせぇー本だな・・・。」と思う本の一つだったので。。
ポール・グレアムがオススメしているとなると読みたくなる不思議。

しかし、一体どうやってそんな古書を・・・。。

人を動かす 新装版

2010/08/29

数学入門(上)遠山啓 著

数学が嫌いな方、算数で挫折した方にオススメしたいです。

私も算数で躓いて、中高の数学はなんとかやり過ごして大学は文系に行ったクチです。10代前半に読んでいたら、人生が変わっただろうなと思います。おもしろいしわかりやすいし、楽しんで読めます。数学のおもしろさを感じることができます。

「学校の教科書はコレにした方が良いんじゃないか。」と @shunsuk さんがおっしゃっていましたが、私もそう思います。そうでなくても算数や数学を教える立場にある方には参考にして欲しい一冊だと思いました。

(下)も読みます。これは読みます。

数学入門〈上〉 (岩波新書)

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)

syntax-rules: mreverse (マクロ reverse, 反転)

syntax-rules による reverse です。syntax-rules でマクロを書く時に良く使われるテクニック(?)。

helper を別途定義した場合。


プログラミングGauche

2010/08/26

syntax-rules: cut っぽい let

たまたま、試しにこういうアナフォリックマクロを書いていました。値を一時的に束縛したいけど、名前を付けたいわけではないことがよくある気がしたので。別に <> じゃなくて On Lisp の aif や aand みたいに it でも良いんですけども。

そこで、srfi-26 の cut っぽい let があったら便利そうだなぁ。。と思ったので、こちらも試しに書いてみました。みましたが・・・。(名前は、cut っぽい let -> cutlet -> cet と取りあえず)

ネストした時ダメですね。。こういう時はどう扱ったら良いんでしょうか。わかりません。以下のように少し書き足してもみましたが・・・。動いたとしても、ここまでするなら一番最初のアナフォリックマクロで良いかなーと思いました。


しかし、srfi のコードは美しいですねぇ。今回も大変勉強になりました。

追記

コメント欄が面白かったので。

プログラミングGauche

2010/08/25

Gauche の $ (ドル)

コメント欄の Gauche の $ 
$ の話をどこかで見たなー・・・と思ってググるもなかなか見つかりませんでした。Haskell 由来だった覚えがあったので「Gauche Haskell」でググったら出てきました。。
gauche.experimental.app なんてものがあるんですね。ドキュメントにもない実験的な機能ということですか。$ もこれに含まれているようです。(Gauche もいずれリーダーマクロがつくっぽいところも期待)

似てるけど違うけど、これを思い出しました。

追記


プログラミングGauche

Visual Stuidio (2008) での Emacs キーバインド

ツール -> オプション -> 環境 -> キーボード
キーボードマップ スキームを Emacs に設定後、以下の設定を追加してみました。

キー 実行されるコマンド
C-c i 編集.選択範囲のフォーマット
C-h 編集.一語削除
M-; 編集.選択範囲のコメント
M-+ 編集.選択範囲のコメントを解除
C-, ウィンドウ.前のドキュメントウィンドウ
C-. ウィンドウ.次のドキュメントウィンドウ

たったこれだけですが、追加したら結構良い感じになりました。

あとは
C-g を Emacs と同じようなキャンセルっぽい動作に
tab の入力を C-i に
補間候補のポップアップ内の選択も C-n, C-p に できたらもっと幸せなんですが・・・。

ところで、VS2010 では Emacs キーバインドがデフォルトでは提供されていないとか。

そういや、こういう噂はどうなったんでしょうね。


参考

Emacsテクニックバイブル ~作業効率をカイゼンする200の技~

2010/08/24

グッド・ラボラトリー・プラクティス

同じくただのメモ。

世界は分けてもわからない P.186 より。
実験室におけるよき習慣。ヒトは常に間違える。忘れる。混乱する。だから、それをしないよう注意するのではなく、それが起こらないための方法論を考えよ。あるいはミスが起こったとき、その被害が最小限にとどまるような仕組みを考えよ。それが君たちの仕事だ。

プログラマの仕事のことかと思いました。どの業界も似たようなものなんでしょうか。ソフトウェア業界にも似たような教訓があります。
それに福岡伸一さんの著書を読むと、ポスドクの社畜っぷりもなかなかであることがわかります。

そういえば、この 世界は分けてもわからない には意外なことに、ゲームプログラマになる前に覚えておきたい技術 の平山尚氏の名前が出てきます。

世界は分けてもわからない (講談社現代新書)

「足りない」という強迫観念

世界は分けてもわからない P.14 より。
私の身体が、あるいは私の精神が不調なのは、何かが不足しているからかもしれない・・・・・・この強迫観念から逃れんがための反動として、私たちは時として、不必要な物質の大量摂取を無自覚に行なってしまうのです。
↑を読んで↓を思い出しました。

「過ぎたるは及ばざるが如し」「押し付けられた善意は悪意と同じ」ですか。

生物と無生物のあいだ (講談社現代新書) と できそこないの男たち (光文社新書) も以前読みました。次は 動的平衡 生命はなぜそこに宿るのか も読んでみたいです。


最近ようやく積読が増加から減少傾向に。。

世界は分けてもわからない (講談社現代新書)

2010/08/20

「Scheme」という名の由来

ここだけ引用してもアレですが。。
英語でPlannerはプランする何かです。Conniverはスニーキー(こそこそする、卑劣)なプランナーです。だから、もっとスニーキーなプランナーを何と呼ぼうか。そりゃ、スキーマー(陰謀家、策略家)だ。それで、Schemerとつけたのです。

残念ながら、我々は60年代に設計されたOSを使っていたので、すべてのファイル名は6文字以下でなければなりませんでした。それで、ファイル名SCHEMERは最初の6文字だけに切り捨てられました。

概略

MIT に Carl Hewitt と Gerry Sussman という聡明な二人が競い合ってプログラミング言語を実装していた。

Carl Hewitt が Planner というとても複雑なプログラミング言語を設計した。
Planner が複雑過ぎて実装できなかったため、Planner の小型版である Microplanner が実装された。
それでも複雑だったため、Gerry Sussman が Microplanner を改良した Conniver という言語を実装した。

一方 Carl Hewitt は、Conniver より良い Plasma という言語を実装した。
Plasma は Smalltalk などから影響を受けた、アクタモデルを採用したオブジェクト指向言語だった。Plasma にはコンティニュエーション(継続)の概念があった。

Plasma は難し過ぎて、Gerry Sussman と Guy L. Steele Jr には理解できなかった。
二人は、不要な機能を取り去ったとても小さな Plasma のインタプリタを Lisp で書いた。
Gerry Sussman はこのころレキシカルスコーピングに興味があったのでそれを採用した。

Sussmanと私は、小さなインタプリタを書きました。言語を理解するもっとも簡単な方法はそのインタプリタを書くことです。インタプリタを書くもっともよい言語はLispです。

Planner, Conniver ときたので、Schemer と名付けることにした。
OS の制限でファイル名が6文字までしか許されなかったので6文字以降を切り捨てた Scheme になった。

余談

Gerry Sussman は SICP の中の人ですね。
Guy L. Steele Jr は Common Lisp や Java の仕様策定なんかもやった人ですね。



レキシカルスコープとダイナミックスコープ

  • scheme
    • レキシカルスコープ
  • Common Lisp
    • レキシカルスコープ
    • ダイナミックスコープ
  • Emacs Lisp
    • ダイナミックスコープ
という認識で良いかと思います。Clojure や Arc なんかもたぶんレキシカルスコープでしょう(たぶん)。
Common Lisp はスペシャル変数(だけ?)がダイナミックスコープですよね。

scheme にはダイナミックスコープな変数をエミュレートする fluid-let という変数束縛マクロがあったりします。
で、なんと Emacs Lisp には lexical-let マクロという、レキシカルスコープな変数をエミュレートするマクロがあるらしいじゃないですか。(cl パッケージだけど)
ソース見てみたんですが、正直よくわかりませんでした。。

Emacs Lisp と lexical-let の場合。
(require 'cl)

(defvar a 100)
a
;; 100

(defvar b 200)
b
;; 200

(defun a+b ()
  (+ a b))

(a+b)
;; 300

(let ((a 1)(b 2))
  (values (a+b)(+ a b)))
;; (3 3)

(lexical-let ((a 1)(b 2))
  (values (a+b)(+ a b)))
;; (300 3)

ついでに、scheme と fluid-let の場合。
(use srfi-15)

(define a 100)
a
;; 100

(define b 200)
b
;; 200

(define (a+b)
  (+ a b))

(a+b)
;; 300

(let ((a 1)(b 2))
  (values (a+b) a b))
;; 300
;; 1
;; 2

(fluid-let ((a 1)(b 2))
  (values (a+b) a b))
;; 3
;; 1
;; 2

Scheme 以前の太古の Lisp は皆ダイナミックスコープだったらしいですね。こわい。
Common Lisp のスペシャル変数は便利だなぁ、と思っていました。でも Emacs Lisp のように原則ダイナミックスコープっていうのはどうなんだろう。すごく難しそうな気がするんですが、どうなんでしょう。。

2010/08/19

Emacs Lisp の mapcar

ハマった。。apply を疑ったり。。

mapcar が引数に取るリストは、単一なんですね。複数のリストを取るのは mapcar* だそうで。

これは error

(apply 'mapcar 'cons '(("1" "2" "3")("a" "b" "c")))


複数のリストを取るのは mapcar*

(apply 'mapcar* 'cons '(("1" "2" "3")("a" "b" "c")))
(mapcar* 'cons '(1 2 3)'(a b c))
(mapcar* 'list '(1 2 3)'(a b c)'(10 20 30)'("a" "b" "c"))


Emacsテクニックバイブル ~作業効率をカイゼンする200の技~

fold-with-index

書かなくてもあった・・・

プログラミングGauche

2010/08/17

Project Euler お試し

追記

丸3年放置していましたが、2013/08/07辺りから再開しました。


shunsuk さんの勧めで、取りあえず1問やってみました。こういう場合、勧めなのか薦めなのか。。

以下コード。
いつものことですが、名前付けがどうもしっくりこないです。かと言って英語の勉強まで手を広げる気にもなれません。

Project Euler は数学色が強いと聞いていたので敬遠していましたが、取りあえず躓くまでやってみようと思います。
L-99 の方も滞っています。

そうえば Chrome がバージョンアップして Ctrl+b でブックマークバーが出なくなって戸惑いました。Ctrl+Shift+b になったんですね。

数学入門〈上〉 (岩波新書)

2010/08/13

syntax-rules:def-let* (slib)

syntax-rules でマクロを定義するマクロ def-let* がうまいこと動きませんでした。
これがその def-let*

そこで、また教えて頂きました!ありがとうございます!
@valvallow http://bit.ly/9Bvqri
@valvallow まず (use slib)(require 'repl)(require 'syntax-case) とします。 slib 環境内で評価したい式全体を quote して macro:eval 手続きに渡せばよいです。
@valvallow あるいは、 (repl:top-level macro:eval) とすると slib の repl が開始されるのでここに式を入力してもよいです。

動きましたー!以下そのコード。仕組みがよくわかってませんが。。

slib は今まで (use slib)(require 'trace) して trace, untrace くらいしか使ったことありませんでした。。slib って R5RS 準拠の pure scheme なライブラリなんですよね?srfi も良いですが、slib も読むと面白そうですね!

プログラミング言語SCHEME

2010/08/12

syntax-rules: fluid-let*

なんのことはありません。fluid-let を使って fluid-let* を書くわけですから、let を使って let* を書くのと変わりません。

;; fluid-let*

;; ;; example
;; (define-values (a b c)
;;   (values 1 2 3))

;; (define (a+b+c)
;;   (+ a b c))

;; (a+b+c)
;; ;; 6

;; (fluid-let* ((a 100)
;;              (b (* a 2))
;;              (c (+ a b)))
;;             (a+b+c))
;; ;; 600

つまり、以下のコードのようになります。

そうなると、こういうのが欲しくなります。(このコードは動かないと思います。)

syntax-rules でこういうの書くにはどうしたら良いんだろう。。たぶん、... のところがダメなんじゃないかとは思うのですが・・・。
プログラミングGauche

syntax-rules: fluid-let

fluid-let は dynamic scope をエミュレートするようなマクロです。

fluid-let は srfi にもあります。gauche などでは組み込みで用意されています。驚いたのは dynamic-wind が使われているところ。例えば body で脱出された場合などを考慮しているんですよね、きっと。なるほど~。

こういう動きです。
;; fluid-let

;; example
(define-values (a b)(values 1 2))

(define (a+b)
  (+ a b))

(a+b)
;; 3

(fluid-let ((a 100)(b 200))
  (a+b))
;; 300

;; fluid-let expand image
(let ((tempa a)(tempb b))
  (dynamic-wind
    (lambda ()
      (set! a 100)(set! b 200))
    (lambda ()
      (a+b))
    (lambda ()
      (set! a tempa)(set! b tempb))))
;; 300
(a+b)
;; 3
独習 Scheme 三週間 Teach Yourself Scheme in Fixnum Days に伝統的なマクロを用いた例が載っています。
fluid-let は syntax-rules では書けないかと思っていました。が、書けるようです。

当初、カンニングせずに自分で考えてみようと思いましたが、syntax-rules 内で一時的な変数を用意する方法がわかりませんでした。。そこで早速カンニングして写経してみました。

当然ですが、srfi のコードは美しいですねぇ・・・。
;; SRFI 15: Syntax for dynamic scoping - http://srfi.schemers.org/srfi-15/srfi-15.html
(define-syntax fluid-let
  (syntax-rules ()
    ((_ ((v1 e1) ...) b1 b2 ...)
     (fluid-let "temps" () ((v1 e1) ...) b1 b2 ...))
    ((_ "temps" (t ...) ((v1 e1) x ...) b1 b2 ...)
     (let ((temp e1))
       (fluid-let "temps" ((temp e1 v1) t ...) (x ...) b1 b2 ...)))
    ((_ "temps" ((t e v) ...) () b1 b2 ...)
     (let-syntax ((swap!
                   (syntax-rules ()
                     ((swap! a b)
                      (let ((tmp a))
                        (set! a b)
                        (set! b tmp))))))
       (dynamic-wind
         (lambda ()
           (swap! t v) ...)
         (lambda ()
           b1 b2 ...)
         (lambda ()
           (swap! t v) ...))))))

写経しつつ以下のように分解してみました。

上記の helper マクロを写経しているときに気づいたのですが、
(_ "temps" (t ...) ((v1 e1) x ...) b1 b2 ...)
     (let ((temp e1))
       (fluid-let "temps" ((temp e1 v1) t ...) (x ...) b1 b2 ...)))
この部分が素敵ですね!自分はこのテクニック(?)を知らなかったので、今まで以下のように書いていました。。

ところで、文字列を使ったフラグ(?)によって、以下のように一つのマクロにまとめることができるわけです。

でも、こういう風に書けたらもっとわかりやすい気がします。でも、確かダメなんですよね。。(... ...)とかドット対記法だと良いんでしたっけ?(その辺はまた今度・・・)



参考


;; SRFI 15: Syntax for dynamic scoping - http://srfi.schemers.org/srfi-15/srfi-15.html
(define-syntax fluid-let
  (syntax-rules ()
    ((_ ((v1 e1) ...) b1 b2 ...)
     (fluid-let "temps" () ((v1 e1) ...) b1 b2 ...))
    ((_ "temps" (t ...) ((v1 e1) x ...) b1 b2 ...)
     (let ((temp e1))
       (fluid-let "temps" ((temp e1 v1) t ...) (x ...) b1 b2 ...)))
    ((_ "temps" ((t e v) ...) () b1 b2 ...)
     (let-syntax ((swap!
                   (syntax-rules ()
                     ((swap! a b)
                      (let ((tmp a))
                        (set! a b)
                        (set! b tmp))))))
       (dynamic-wind
         (lambda ()
           (swap! t v) ...)
         (lambda ()
           b1 b2 ...)
         (lambda ()
           (swap! t v) ...))))))


;; Identifier Syntax - http://permalink.gmane.org/gmane.lisp.scheme.reports.wg1/148
(define-syntax fluid-let
  (syntax-rules ()
    ((fluid-let ("step") bind ((var val) . rest) body ...)
     (fluid-let ("step") ((var old new val) . bind) rest body ...))
    ((fluid-let ("step") ((var old new val) ...) () body ...)
     (let ((old var) ...
           (new val) ...)
       (dynamic-wind (lambda () (set! var new) ...)
                     (lambda () body ...)
                     (lambda () (set! var old) ...))))
    ((fluid-let ((var val) ...) body ...)
     (fluid-let ("step") () ((var val) ...) body ...))))


;; http://www-pu.informatik.uni-tuebingen.de/users/knauel/sw/fffi/easyffi.scm
(define-syntax fluid-let
  (syntax-rules ()
    ((fluid-let ((var1 expr1) (var2 expr2)) body ...)
     (let ((old-var1 var1)
           (old-var2 var2))
       (set! var1 expr1)
       (set! var2 expr2)
       (let ((res ((lambda () body ...))))
         (set! var1 old-var1)
         (set! var2 old-var2)
         res)))
    ((fluid-let ((var1 expr1)) body ...)
     (let ((old-var1 var1))
       (set! var1 expr1)
       (let ((res ((lambda () body ...))))
         (set! var1 old-var1)
         res)))))


;; Control Operations - http://www.scheme.com/tspl4/control.html
(define-syntax fluid-let
  (syntax-rules ()
    [(_ ((x e)) b1 b2 ...)
     (let ([y e])
       (let ([swap (lambda () (let ([t x]) (set! x y) (set! y t)))])
         (dynamic-wind swap (lambda () b1 b2 ...) swap)))]))

The Scheme Programming Language, 4th Edition

2010/08/11

Gauche の and-let* と On Lisp の aand

On Lisp の aand をそのまま scheme で以下のように書いてハマりました。。

まともに使うにはこうでしょうか。。

というか、gauche を使っているので、and-let* を使った方が無難なようです。。


プログラミングGauche

2010/08/08

(append '() 'a) ; -> a

gauche で (append '() 1) を評価した結果が 1 になるのはなんとなく納得いかないなぁ...
これを見て私もまんまと「え、なんでだろう?」と思いました。
shiro: R5RSでそう規定されてます RT: @yujiorama: gauche で (append '() 1) を評価した結果が 1 になるのはなんとなく納得いかないなぁ... http://bit.ly/atJY60
で、実際 R5RS を見てみたら、そう書いてありました。そらそうですね。
shiro: appendは正式なリスト同士の演算じゃないんですね。むしろペアに対する演算の一種と考えた方がすっきりする。consやlist*の仲間。 http://bit.ly/9eMywh
@valvallow いや、一貫してるでしょう。 リストの最後 (null) を次のリストに置き換えた形にするものと考えれば。
ここまで読んでもピンと来ませんでしたorz
下記のように append を自分で書いてみてようやくわかりました。。orz (append '() 'a) ; -> a なのは当然の結果ですね。


プログラミングGauche

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

defmacro: def-related-closures

思いついたので書いた。後悔はしていない。必要ない気がする。


On Lisp

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)

2010/08/04

「LISPにはscanlに該当する関数ってあるんでしょうか?」

指名ktkr!!力不足ですが、せっかくですので。
ところで、LISPにはscanlに該当する関数ってあるんでしょうか? > valvallowさん
正直わかりません、知りません、すみません。。Haskell 読めませんが、fold っぽいですね。取りあえず確認がてら同じようなものをでっち上げてみます。遅延評価でもなく Gauche 依存ですけれども。以下コード。

非常にカッコ悪いですね・・・。なんでこんなに難しそうになるわけ・・・。


素直に named-let で書いた方がよかったみたいです。


きっと R5RS の範囲の Scheme にはないんじゃないでしょうか。たぶん R6RS にも。srfi か Common Lisp にはあるかも?教えてエロい人!

追記

そうか。fold2 で書くにしても、こうすれば receive 取れて少しマシか。


追記2

毎度のことながら教えていただきました!
@valvallow (use gauche.collection)(define (scanl f x xs)(values-ref (map-accum (^(a acc)(let1 z (f a acc) (values z z))) x xs) 0))
なるほど、map-accum ですかー!ちょっと写経。

values-ref ってのもあるのか。


追記3

Clojure で書いてる人がいらっしゃる。

追記4

遅延評価だとこんな感じ?いや、良くわかりませんが・・・。


追記5

また教えていただきました!ですが、マニュアル見ても iterator->stream がよくわかりません。。
@valvallow (use srfi-1)(use util.stream)(define(scanl f x xs)(iterator->stream(lambda(n e)(until(null? xs)(n x)(set! x(f x(pop! xs))))(e))))
せっかくなので、インデント付けて gist に貼っつけました。


プログラミングGauche