ひ日誌
2004-10-01 ( ja -> en )
_ SICP攻略戦 - ゲリラ戦を展開するであります
SICP*1を冒頭からきっちり読もうとすると、あっという間に撃沈される。敵の守りは堅い。これまで何度か真正面からの白兵突撃を試みたが、つぎつぎと繰り出される敵弾の前にひとたまりもなく撃滅されてきた。
そこで戦術変更。側面から神出鬼没に攻撃を加えるゲリラ戦を展開してみることにした。これが意外に効果があった。当面、この戦術で敵を消耗させることにしよう。
というわけで、並列のところを眺めようとページを繰ってるうち、なぜかストリームの冒頭のところへ。
前節あたりで、状態をモデル化する手法として、状態の時間変化を局所変数への代入で表現する方法とその問題点について、云々したらしい。これはおそらくOOPな人が日常的に使っている手法、オブジェクトがあって属性があって破壊的だのとか、そのあたりのことではなかろうかと推測。
ここでは。もうひとつの解決方法としてストリームを使うという。ストリームと遅延評価を使うと、局所変数への代入を使わずに、状態を持つシステムをモデル化できるらしい。これは自分が気付いていなさそうだ。なんだか新しい発見を予感させるではないか。
難攻不落のSICP*2だが。目次とかで関心のある箇所を拾い読みしてみたら、面白く新しい発見がありとっつきやすいことに気付いた。抽象があってそれをどう応用するのかといった視点でシステム設計を語る、ってのはいいもんだ。要するにそういうことだ。
2004-10-05 ( ja -> en )
_ Firefox をアップデート
したらブックマークがまるまる消えてもた。
_ UML図のようなものを書く
どういう風の吹き回しか、なんだかものすごいことになってるC++のソースコード*1を読んだりいじったりしてる。わけわかんねーと思ってたのだが、このソースコードからUMLのクラス図のようなものを書き起こしてみたところ、だいぶ見通しがよくなった。
*1 というかすべてのC++ソースコードがものすごいことになっているように見える体質だと思う
2004-10-06 ( ja -> en )
_ Portable Object Compiler
<URL:http://users.pandora.be/stes/compiler.html>
Objective-Cは、インライン Smalltalk の書ける C というか、インライン C の書ける Smalltalk というか、そんな風味の本物のオブジェクト指向言語であろう。なんちゃってオブジェクト指向言語ではくせ球・変化球を屈指してプログラミングする必要があるが、本物の場合そんなトリックを使う必要はない。直球勝負のオブジェクト指向プログラミングが可能だ。
Objective-C は gcc にも含まれているが、それとは別にPortable Object Compilerという処理系がある。 これにはいくつかの興味深い特徴があるのだが、中でも際立つのは Objective-C blocks だ。
[ary do: { :item | [self remove: item]; } ];
とか
id block = { :item | [item printOn: stderr]; };
[ary do: block];
みたいなことが。。ぐっ!Ruby みたいだ。
僕は数年前にとある仕事で一度使ったことがあるのだが、その後使う機会もなく忘れていた。はたしてこれを使ってる人はいるんだろうか。なんだかとてもマイナーな存在のような気がする。
_ 屋上カメラの映像
「ご覧のように横に揺れています」と言われても。。 USSエンタープライズに光子魚雷が着弾、したようなものか?
2004-10-08 ( ja -> en )
_ [lisp] LISPマクロの書き方
ちょっとだけ学んだ。ややこしそうだという先入観があったのだが、「ANSI CommonLisp」を読みつつコードを書きながらやったところ、結構すんなりといった。リーダーズマクロというのも要チェック。
_ [rubycocoa] 放置しっぱなしでごめん
<URL:http://d.hatena.ne.jp/ogijun/20041008#p2>
こういう記事(An Introduction to RubyCocoa)があるとは知らなかった。いろんなところで話題にしてもらえるのはうれしいことです。 だというのに、すっかり放置していて申し訳ない。 kimurawさんにちゃんとお願いして引き継いでもらった方がいいのだろうと思いつつ何もしてません。
Dave Thomasさんのサイン本を入手されたようでうらやましいです。
_ 直球勝負は気分がとーってもいい
<URL:http://homepage.mac.com/mkino2/backnumber/2004_10.html#October%2008_2>
いやぁだけど「Effective-C++」は、C++ のコードと格闘中の人*1には、便利な魔法のレシピ集といった風でなかなかいい本だと思いますよ。。。。。となぜかフォロー。
ここで自分がどんな C++ の本を持ってるか確認してみると:
- Effective-C++
- 現実的なC++プログラミング - ちょっと古いがこれも C++ マジック集として結構いい内容
- The C++ Programming Language 3rd Ed.
- プログラミング言語 C++ 第3版
があった。Stroustrup の本を、英語版・日本語版と2冊とも揃えちゃってるよ。 日英版両方持ってるなんて、他にはヒレガスのCocoa本だけだ。ほんとは自分、C++好きなんじゃないか?
それからデザインパターン。こんなテクニック使わなくても Ruby とかなら普通に書けるよ、みたいなことは結構ある。だけど、それでもデザインパターンのGOF本はとてもいい本だと思う。「アジャイルソフトウェア開発の奥義」でのデザインパターンの解説もなかなかいい。
なんというか、実際にコードを書いた経験に基づいていることが匂ってくるソフトウェア技術本はいい。
なんかとりとめもない文になってしまった。。。。
*1 自分のことだったりする
2004-10-11 ( ja -> en )
_ Duck Typing
という言葉をよく見かけるが意味を知らなかったので調べてみた。 あおきさんの日記にあった:
「猫っぽく見えるなら猫ってことにしとけばいいじゃん」という、現代的・殺那的な考えかた。にゃーと鳴いたら猫。わんと鳴いたら犬。respond_to?(:each) なら Enumerable。
という定義を読んで「なんだ、それのことか!」と納得してしまった。 納得したら <URL:http://c2.com/cgi/wiki?DuckTyping> の英文を読むのが面倒になって読んでない。それでいいんだろうか?だいじょうぶたろうか?
_ 『Programming Ruby 2nd Edition』の改訂点を目次から邪推
<URL:http://www.objectclub.jp/ml-arch/magazine/67.html>
これを読んだらやはり欲しくなってきた。Duck Typing が章になっているらしい。
_ ぼくがきみのプログラミング言語できらいなもの
<URL:http://kumiki.c.u-tokyo.ac.jp/~ichiyama/mt/archives/000007.html>
それぞれの言語に長短があり適材適所で使えばいいじゃん、というようなところか?「僕がC言語できらいなところ」の:
これはしょっちゅう不適切に使われる。ぼくはカーネルやデバイスドライバ、仮想マシン、またはCやC++のライブラリのインタフェースを書いてないのであれば、 Cで書くことはおそらく早すぎる最適化だろう。
このことを言いたい局面というのがときどきあって、どうもうまく表現することができなかったのだが、これからはこれを使える。
2004-10-12 ( ja -> en )
_ [lisp] Lisp でオブジェクト指向すると (2)
「ANSI Common Lisp」の CLOS のあたりを読んだ。メッセージ伝達モデルが総称関数モデルに還元される、というようなことはなるほどとは思った。でも補助メソッドのあたりなど「こんな過剰なのはどうもあれだな..」と思ってしまった。こちらは、クラス継承モデルを汎化するという路線なのだろうか?
さて、CommonLisp で局所変数を共有する関数を:
(let ((cnt 0)) (defun cnt-val () cnt) (defun cnt-inc () (setf cnt (+ cnt 1)) cnt) (defun cnt-dec () (setf cnt (- cnt 1)) cnt))
のように書けるが、これを Scheme で書こうとしたら:
(begin
(define cnt-val #f)
(define cnt-inc #f)
(define cnt-dec #f)
(let ((cnt 0))
(set! cnt-val (lambda () cnt))
(set! cnt-inc (lambda () (set! cnt (+ cnt 1)) cnt))
(set! cnt-dec (lambda () (set! cnt (- cnt 1)) cnt))))
こんな風なのしか思いつかなかった。しかし、「局所変数を共有する関数」を「インスタンス変数を共有するオブジェクトとそのメソッド」というように解釈したら:
(define (counter-new . n)
(let ((cnt (if (null? n) 0 n)))
(lambda (msg)
(case msg
((:val) cnt)
((:inc) (set! cnt (+ cnt 1)) cnt)
((:dec) (set! cnt (- cnt 1)) cnt)))))
こんに風に書けて:
(define cnt (counter-new)) (cnt :val) (cnt :inc) (cnt :dec)
のように使える。なかなかかっこいい。逆にこれを CommonLisp で書くと:
(defun counter-new (&optional n)
(let ((cnt (or n 0)))
(lambda (msg)
(case msg
((:val) cnt)
((:inc) (setf cnt (+ cnt 1)) cnt)
((:dec) (setf cnt (- cnt 1)) cnt)))))
とここまではいいのだが:
(setf cnt (counter-new)) (funcall cnt :val) (funcall cnt :inc) (funcall cnt :dec)
となる。funcall が暑苦しい。。。見た目を気にしているようではダメか?「そこでリーダーマクロですよ」というささやきも聞こえた。 自分はどっぷりメッセージ伝達モデルの人らしい。
2004-10-14 ( ja -> en )
_ [lisp] Common Lisp - 暑苦しい funcall を略記する入力マクロ
20041012 の続き。以下のような入力マクロを作ると:
(set-macro-character #\] (get-macro-character #\)))
(set-dispatch-macro-character #\# #\[
#'(lambda (stream ch1 ch2)
(let ((lst (read-delimited-list #\] stream t)))
(list 'apply (car lst) (list 'quote (cdr lst))))))
20041012 で定義した関数 counter-new によって生成したメッセージ伝達モデルのオブジェクト風味クロージャ:
(setf obj (counter-new 10))
にメッセージを送るのに:
(funcall obj :inc) ; => 11
と funcall を明示的に書いていたところを:
#[obj :inc] ; => 12
と書くことができるようになった。
'#[obj :inc] ; => (APPLY OBJ '(:INC))
と展開されてから評価される。「#[」と「#]」は、ユーザ用に使っていいことになっているので問題ない。 しかし、この程度の入力マクロを書くのにもちょっと難儀した。なかなかややこしい。
さて次は:
'#{ a b | ... } ; => (lambda (a b) ...)
と展開されるような入力マクロも欲しいような気がしたりする。
#[obj :each #{ i | (write i) } ]
とか。悪のりしすぎか?
2004-10-17 ( ja -> en )
_ お風呂で読める文庫本
- <URL:http://slashdot.jp/article.pl?sid=04/10/17/0142218&topic=102>
- <URL:http://www.asahi.com/business/update/1017/001.html>
一お風呂読書愛好家としては、こういう商品が出るのは歓迎である。 小説の名作などが中心で今後はマンガなども予定とのことらしい。
商品の性質上やや高めな値段設定だが、小説やマンガではわりとすぐ読み終わってしまい、ややコストパフォーマンスが悪い。マンガなどひと風呂程度で読み終わってしまうのに700円となると、スーパー銭湯なみだ。私としては:
- お風呂で読める「エレガントな宇宙」
- お風呂で読める「ファインマン計算機科学」
といったものを希望*1。「お風呂で科学シリーズ」。これらの本は非常にコストパフォーマンスが高い。さらに:
- お風呂で読める「計算機プログラムの構造と解釈」とお風呂で動く「Schemeインタプリタ」セット
風呂でぼんやりしてるときに何かを思い付くことはありませんか?そんなときにうれしい一品です。
*1 わりと本気であるといいと思うのだが出るわけないだろうな
2004-10-20 ( ja -> en )
_ オブジェクト指向プログラミングを語るなら...
「オブジェクト指向」を語るならその歴史や背景を知っておけ、というような立場(だと思う、おそらく)から、「オブジェクト指向」を語る日記にたどり着く。自分の見落としていたことが見えたりする。博識で参考になりそう。
もっとも、「特異メソッドの例にはどんなのがいいか」あたりなど、微妙に違和感というか問題がズレているように感じた部分もあったりした。「じゃあどうズレてるんだ?」と聞かれると、知識の物量に圧倒されたせいかよくわからない。自分の勘違いかも。。。とりあえず落し穴にはまらないように意識しながら読んだ方がよさそうな気はする。
_ 「違和感」などと書いておいて何も書かないのはズルいですよね
すみません(汗)。ということで特異メソッドの例にはどんなのがいいかについて、どんな風に感じたか文章化してみました。
(defmethod is-zero (self) NIL) (defmethod is-zero ((self (eql 0))) T)
が意味するところを Ruby に置き換えるとして:
def is_zero; false end def 0.is_zero; true end
とするのは、Ruby にはない CommonLisp の特徴であるところの総称関数モデル、に引きずられていないだろうか?
また、Lisp版 is-zero の最初の引数が self と名付けられていることから、これは総称関数でメッセージ伝達モデルを表現したというように解釈することもできて、するとこの場合、同じことを Ruby で自然に表現するとすれば:
class Object def is_zero; self == 0; end end
のように is_zero を Objectクラスのインスタンスメソッドするのがよいのではなかろうか。 だとするとこの例と特異メソッドはあまり関係ないんじゃないかな。
。。。こんな感じのような気がします*1。
僕はつい最近、CommonLisp の defmethod による総称関数モデルを知った上、EQL スペシャライザというおもしろい書き方ができることはsumim さんの日記で知りました。というような段階なので見当違いなこと言ってるかもしれません。
_ 特異メソッドといえば...
僕の場合、特異メソッドを直接定義することはあまりないけど(irbで叩くときくらい)、何かの機能を追加するための Mixin モジュールをあらかじめ用意しておいて:
obj.extend PresentationFacility
のように必要になったらオブジェクトに装着する書き方はときどき使います。
*1 なんか重箱の隅をつついてるような気分になってしまった(汗
2004-10-21 ( ja -> en )
_ なんちゃってオブジェクト指向の逆襲
ある有名なオブジェクト指向言語で書かれたコードを読んでいて、どうにも意図を掴みかねる部分があった。その箇所は map*1 を使っている。さんざん頭をひねったあげく map について調べてみた。map のイテレータはキーの昇順で繰り返す......えっ?
あらためて読んでみるとコードはその性質に依存して書かれていた。。。。やられた。順不定だと思い込んで調べもしなかった自分が悪いのだが。なんちゃってオブジェクト指向よばわりしたしっぺ返しかもしれない。。。ごめんなさい。
*1 厳密には標準ライブラリの map を模した独自実装
2004-10-23 ( ja -> en )
_ 朝っぱらから濃いブルース
7:45ころに NHK FM でかかったブルース。演奏や雰囲気がすばらしい。ぼんやりしてたので演奏者などの情報を聞き逃した。いつもぼんやり聴いてるのだが、こういうのがかかるたびにラジオ録音環境をつくろうと思う。だが後の祭り。同じことを繰り返してる。
さて、このピーターバラカンさんの番組はいい。自分でおもしろそうな音楽を見つけるのは面倒だからなかなかやらない。自分でやるとそれだけでお腹いっぱいになったりもする。だが、この番組が自分のかわりにジャンルにとらわれずおもしろい音楽をマニアックぎみに集めてかけてくれてるみたいだ。たいへん素晴しい。いつまでも続いて欲しい。
ピーターバラカンさんのしゃべり(もちろん日本語)がとても聞き取りやすいのもいい。おそらく母国語が英語の人だと思われるのに、番組中で URL を読むときのアルファベットの発音が完璧に日本人風*1なのがおもしろい。この人より日本語の聞き取りづらいアナウンサーやキャスターはざらにいるような気がする。
*1 えっちてぃーてぃーぴーころんすらっしゅすらっしゅだぶるだぶるだぶるどっとえぬえいちけーどっとおあどっとじぇーぴー
2004-10-24 ( ja -> en )
_ 「この問題を解くことに意味があるのだろうか?」
もちろんその問題はすでに解かれている!しかしそれがどうした?その問題を楽しむために解きなさい。
「ファインマン計算機科学」P.14。ものごとの理解の深め方について熱く語るファインマン。
2004-10-27 ( ja -> en )
_ [lisp] object-apply 発見 - Lispでメッセージ伝達モデル
20041014#p01あたりのことは、 LISP(CLOSなど)でメッセージ伝達モデルOOPで書くとして、Ruby などでとても気に入っている点のひとつである、最左のレシーバを起点にメッセージを連鎖的につなげる:
rcv.sort.map{|i| ... }
みたいに書き方はできないだろうか、というのがそもそもの発端である。
Gauche のリファレンスを眺めてたら見つけた。object-apply:
手続きでもジェネリックファンクションでもないオブジェクトが何らかの引数に適用されたとき、そのオブジェクトと引数がジェネリックファンクション`object-apply' に渡されます。
これだ!ということで試してみた。まず Gauche のオブジェクトシステムで <counter> クラスを定義。
(define-class <counter> ()
((value :init-value 0 :init-keyword :value :getter value)))
(define-method increment! ((rcv <counter>) . args)
(slot-set! rcv 'value (+ (slot-ref rcv 'value)
(if (null? args) 1 (car args))))
(slot-ref rcv 'value))
(define-method decrement! ((rcv <counter>) . args)
(slot-set! rcv 'value (- (slot-ref rcv 'value)
(if (null? args) 1 (car args))))
(slot-ref rcv 'value))
このまま普通に使うと:
(define o (make <counter>)) (value o) ; => 0 (increment! o) ; => 1 (increment! o 23) ; => 24 (value o) ; => 24
となる。メッセージ伝達モデル的記法するためには object-apply を:
(define-method object-apply ((rcv <object>) (msg <generic>) . args) (apply msg (cons rcv args)))
と定義しておく。すると:
(o value) ; => 24 (o increment!) ; => 25 (o decrement! 45) ; => -20 (o value) ; => -20
のようになる*1。これだよ! これで Ruby であげた例を書くと:
((rcv sort) map (lambda (i) ...))
こんな感じか?うーむ、括弧がうっとおしい*2。そなこと思ってたらLispのコードは書いてらんないが。。。 というか map の引数順が逆になるな、こりゃ。
2004-10-30 ( ja -> en )
_ ラジオで今かかってる曲が。。。
まんま Shine On You Crazy Diamond (Pink Floyd) と同じだ。ものすごく同じだ。いーのか、こんなに同じで?というか同じ曲なのか?(7:59 NHK-FM)
ボズスギャックス(スペル不明)のデビュー曲と言っていたような気がする。とても似てることにはひとことも触れられなかった。アンタッチャブルなのだろうか?というか同じ曲なのか?
_ ラジオでさっきかかってた曲が。。。
とてもすばらしい(8:50あたり)。オールマンブラザースバンドで「エリザベスリード」というタイトルだったか?ライブ収録。いつもぼんやり聴いてるので情報があいまい。さっきの曲が Pink Floyd と同じだったせいか、プログレ*1っぽく聴いてしまった。
*1 どうにも恥ずかしい言葉なのだが。どちらかと言えば進歩というよりは伝統芸能っぽいし
2004-10-31 ( ja -> en )
_ ほんとに 2r-1 ですか?ファインマンさん
2つの r ビットの数を加え合わせる加算器を作るのにいくつの単ビット加算器が必要か?
という問いが「ファインマン計算機科学」に出ており、2r-1 個が必要とある。しかし自分で(直球で)解くと、2r-1 個の単ビット加算器に加えて r-1 個のORゲートが必要になってしまう。
単ビット加算器は ANDゲートとXORゲート各1つから構成されている。XOR で NOT が作れ、NOT と AND で OR が作れるので、これをいくつか組み合わせて ORゲートを作ることはできる。しかしその前にすでに 2r-1 個使っている。
わからん。ほんとに 2r-1 でできるの?これがわからないのはやばいだろうか?ファインマンさん、ヒントくれ。
単ビット加算器の仕様 (a,b が入力、s,c が出力):
a b | s c ----+---- 0 0 | 0 0 0 1 | 1 0 1 0 | 1 0 1 1 | 0 1
s = a XOR b c = a AND b
_ 加算器やゲートをプログラムで表現してみると
上の問題を解くのに加算器やゲートをプログラムで表現してみた。遅延評価ってこれのことか?つーか接続してみたらちゃんと動いてない。けどこれはなかなかおもしろそうだ。要チェック!
_ sumim [お邪魔します。Objective-C はもともと、Smalltalk のコードを C コンパイラに通すためのプリプロ..]
_ hisa [ギクッ!痛いとこ突かれた。と思いつつきょう(11/12)の日誌に返事書きましたので。。。]