2006/10/27


校正待ちですることがないので(後半はうそ)、Code Golf の "Switchboard" という問題に手をつけてみた。コードを短くすることはともかく、この問題は解法を考えるのが面白かった。いまのところ23位だけど、これが個人的なスキルの限界だと思う。

Scheme は受け付けてない。そうとはしらず最初は暢気に Scheme で書いたことはいうまでもない。しょうがないので Ruby で書き直したんだけど、"gets" だけで標準入力から1行読み取れるなんて。実用的にもほどがある。

2006/10/26


おいしいとんかつの店は三河島の「山き(きは「七」を森のように重ねた字)」だよ! このへん
どうもあんまり知られてないようなので、叫んでおく。

ヒレがびっくり。とんかつといえばロースだと信じてたのに、その常識を覆された。あと、メンチ。ヒレもメンチもそれまでどっちかっていうとバカにしていた料理だったけど、本当にごめんなさい。もちろんロースもうまい。
ただ、メニューが少ないし、キャベツに対する選択肢がソースしかないので、軟弱な人にはおすすめしない。地元ゆえのひいき目っていうのもある。それでも、普通の豚を普通のとんかつとして硬派に堪能したいなら、絶対におすすめ。普通なのに、軽くびっくりするんだよね。外食にはびっくりが必要だと思う。しみじみうまいだけなら家で食うさ。

店内の色紙によると、阿佐谷の「かつ源」という店からのれんわけしたようだ。あんまり知られてなくて、いつも暇そうにしているので、ちょと応援したい。


SICP の ex. 4.11〜4.13 をうろうろしていたら、ようやく set-car! や set-cdr!が set! と根本的に違うことが飲み込めてきた。いままでそんなこともきちんと知らなかったのかよ。

たとえば次の2つの例は、いっけんすると同じ結果になる。つまり a に (0 1 2 3) が束縛された状態になる。
(define a '(1 2 3))
(let ((current-a (list-copy a)))
(set-car! a 0)
(set-cdr! a current-a))

gosh>a
(0 1 2 3)
(define a '(1 2 3))
(set! a (cons 0 a))

gosh>a
(0 1 2 3)
set-car! と set-cdr! の場合には、もともと a が指し示す領域にあったデータが書き換わっている。それに対して set! でやっていることは、もともと a が指し示す領域にあったデータは換わってなくて、a という名前で束縛されていたものを別の場所に cons して作った (0 1 2 3) に 付け換えたにすぎない。

で、この違いを理解していないことが ex. 4.11 付近で評価器が扱う環境の定義をしたりするときにネックになるわけで、define したつもりのものが環境に登録されずに悩むことになったりするのは僕だけか……。ところで「Schemeは十分に抽象的だけどビットが透けて見えることがある」みたいなことを言ったのは誰だっけ?

この話のとってつけたような結論はお好みに合わせて随時読みかえることができます。
  • やっぱりローレベルの知識が足りないやつは帰れってことだよね。そういえばJoelさんもそんなようなことを言ってたなあ。
  • やっぱり参照透過じゃないとだめだよね。びっくりマーク?なにそれ。





どうでもいいけど、僕は、こういう基本的なことを知らなかったという「恥」を恥と承知して公にさらすことには旨味があると思っている。これは、「知らないなりに考えてみたけど間違ってたら誰か教えてね」という意味ではない。なんか、そういう恥2.0みたいなノリじゃない。恥2.0ではブログツールのコメントとかトラックバックとかはてな何とかとか巨大掲示板といったAPIによりあなたの恥を知識と経験に昇華してあわよくばWebコミュニティへのネタを提供します。よかったね。あるいは、「自分は知らないことを知らないまま放置しない向上心と努力あふれる人間であります」というアピールになるという意味でもない。そういう態度がアピールにはなるのは、ぶっちゃけ小学校の教師に対してだけだろう。努力だけはしてるように見える人と、どこで勉強してるかわかんないけどアウトプットをきちんと出している人がいたら、自分は後者と仕事することを選ぶ。

「聞くは一瞬の恥」とかいうけど、僕には、それで教えてもらった内容だけを自分のなかに保存することができない。恥体験と一緒だから内容が見に付くという側面があるように思う。この側面は、自分自身に固有の経験だけから傍証しているものなので、ほかの人にも当てはまるのかどうかは知らない。まあ、恥も外聞もなく分からないことを聞きまくっている人間にろくなスキルを見に付けていない(ように見える)のが多いとは思うけど。

ようするに独学でスキルを得るには恥の追体験が必要ってことだ。将来の自分は、今日書いた内容を恥ずかしく思い返す必要がある。紙の大学ノートに同じことを書いてもいいんだけど、それは「恥」じゃないんだよね。将来の自分は、今日書いた内容を公開したことを恥ずかしく思い返す必要がある。このノートは恥のタイムシフト装置です。

2006/10/24

temp

emacs から blogger に投稿したい。

Atom Publishing Protocol というのがあって、それをemacs から使えるようにする atom-blogger.el というのがあった。設定方法はここに丁寧に解説されている。

Using atom-blogger with emacs to post to blogger
http://phototechnic.blogspot.com/2006/03/using-atom-blogger-with-emacs-to-post.html

emacs への設定だけをしても、captcha が邪魔するらしく、まったく投稿できない。captcha をオフにする方法もよくわからない。さんざんあちこちクリックして、投稿時のcaptcha の横にある「?」マークをクリックすれば captcha を解除するメニューに入れることが気づいた。なにそれ。

で、そのメニューいわく、「Bloggerのスパム対策ロボットにより、このブログにスパム ブログの疑いがあることが検出されました」。

どうやら captcha による投稿時の認証は、ユーザが望んでオンになるものではなく、bloggerの運営者が「スパムブログ」と判断したものに勝手に設定しているらしい。さっきまでこのノートは Link Spam(Wikipedia)に使われてたらしいよ。Wikipedia によると "Search engine spammers, on the other hand, are generally aware that the content that they promote is not very useful or relevant to the ordinary internet surfer."

ぐうのねもでませんって。

2006/10/23

ツインピークスで、クーパー捜査官がこうつぶやくシーンがある(wikiquote)。


Every day, once a day, give yourself a present.
Don't plan it, don't wait for it, just… let it happen.

毎日ひとつ、自分にプレゼントを。
用意したり待ち望んだりするプレゼントじゃなくって、なにげないやつでいい。


クーパーはこのセリフを、確か一杯のコーヒーについて言っていた気がする。恋人のアニーが一緒だったような気もする。いかんせんセカンドシーズンのDVDがいつまでたってもリリースされないので、そんなようなシーンを記憶の中で作り上げていただけかもしれない。どうでもいいけど、アニーとクーパーはショーペンハウアーのネタで盛り上げれるキチガイだ。

そんなわけで、コーヒーを楽しく飲むと、もう一日の楽しみが潰えたような心地になる。

2006/10/17

同じグループの同僚が鼻歌まじりで仕事してたりすると、不思議に自分も仕事に集中できるもんなんだな。集中しようという意識が持て、しかもそれに成功する。一緒に仕事している人間が上機嫌だってことは、彼女の仕事もうまく動いてるってことだ。そんなプラスの気配がいつも充満している職場ならパーティションはかえって邪魔だろう。たぶんバランスボールのある職場にいる人達はそれを知ってる。

生産性のことさらに低い同僚が鼻歌まじりだったりすればイライラが募る。だから、生産性の低い人間を雇い続けなければいけない職場ではパーティションが必要なんだろう。パーティションより必要なものがあるような気がするので、パーティションを作ってくれとはいわない。せめて本棚をください。

2006/10/10

名前付きletをlambda式にしたい。

SICPの第4章では、Schemeの式の評価機をSchemeで書く。こう書くとやたらに抽象的で深遠でカッコよさげに聞こえるけど、まずはプロシージャをいくつかのスペシャルフォームによる表現に均さないといけないからandやorをletをlambdaにするとか、そういうどちらかというとバタ臭い作業が続く。
で、ex.4.8では、名前付きletをlambda式にしろとある。letrecがないので、たぶん正解はinternal defineを使う方法。でも、そろそろ式の表現を変換するだけの作業には飽きてきたので、不必要に解答をややこしくしてみる。つまり、要するに関数を再帰させる話だと解釈して、こういう問題設定にする。

再帰的なプロシージャを抽象化したい。

答えは分かっている。Yコンビネータだ。というわけで、以下はYコンビネータのおさらい。"The Little Schemer"の第9章の翻案ともいう。

まず、再帰を含む関数を用意する。たとえばex. 4.8のフィボナッチ名前付きlet版。
(define (fib n)
(let fib-iter ((a 1) (b 0) (count n))
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1)))))

count≠0 のときに再帰しているので、 count > 0 のときに適当に答えを出してくれる fib-iter-1 というプロシージャが世界のどこかでよろしく定義されていると妄想する。
(define (fib n)
((lambda (a b count)
(if (= count 0)
b
(fib-iter-1 (+ a b) a (- count 1))))
1 0 n))

再帰しないですむようになったので、もうletに名前はいらない。それで、ついでにletをlambda式にしておいた。もちろん、実際には fib-iter-1 なんていう都合のいいプロシージャはないし、もしあっても fib-iter-1 の中にはきっと再帰があるだろう。fib-iter-1 の再帰を片付けるのに fib-iter-2 を妄想し、さらに fib-iter-2 の再帰を片付けるのに fib-iter-3 を妄想し、……嘘をつき続けなければならない。

そこで発想を飛ばして、「fib-iter-1を妄想する」ことを抽象化してみよう。ちょっと分かりにくいけど、妄想したいものを受け取ってfibの中身のlambdaを返してくれるようなプロシージャを作ればいい。つまりこんな感じ。
(lambda (fib-iter)
(lambda (a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1)))))

ただし現実には「妄想の果て」が必要になる。また妄想なんだけど、とりあえず果てに行き付いたので無理矢理納得することにする。妄想の果てを fib-iter-omega とすると、
(define (fib n)
(((lambda (fib-iter)
(lambda (a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1)))))
fib-iter-omega)
1 0 n))


ここで再び発想を飛ばして、今度は「妄想の果て」を抽象化する。それには、妄想を受け取って妄想を返し続けるようなプロシージャを作ればいい。こんな禅問答のようなプロシージャが考えられる。
(lambda (fib-iter) (fib-iter fib-iter))

これってつまり「関数を自分にぶちこむ」ってことなので、「再帰する」ことを抽象化しているとも考えられる。

ところが、実はこれだけだと果てしなく続く妄想だけになっちゃて、妄想の仕様が何も分からない。仕様がないものは使いようがない。そこで、まずは妄想を整形してやって、それを「果てしなく続く妄想」に渡すようにしてやりたい。いま考えているfib-iterでは3つの引数(a,b,const)を使っているので、この「妄想の果て」も3つの引数をとるプロシージャを返すようにしないといけない。
(lambda (delusion)
((lambda (fib-iter) (fib-iter fib-iter))
(lambda (f) (delusion (lambda (x y z) ((f f) x y z))))))

妄想delusionを受け取って、それを3引数を取るプロシージャの形にして、後はひたすら妄想を続けるというノリ。これがYコンビネータ。だからYコンビネータは、妄想を使えるものにするための、どっちかっていうとテクニカルな細工なんだと思う。

以上をfibに取り込むと、こうなる。
(define (fib n)
(((lambda (delusion)
((lambda (fib-iter) (fib-iter fib-iter))
(lambda (f) (delusion (lambda (x y z) ((f f) x y z))))))
(lambda (fib-iter)
(lambda (a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))))
1 0 n))


もうすっかり妄想が抽象化されつくしたので、これはフィボナッチ数列のn項を求めるプロシージャとしてちゃんと評価される。

gosh> (map fib (iota 20))
(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)

2006/10/02

御徒町の工具屋さんにPBの六角レンチを1本買いにいったつもりが、お店の人にそそのかされてStahlwille(スタビレー)のコンビネーションレンチを5本買ってしまった。まともなスパナをもってなかったので、ちょうどいい機会だったと思うことにしよう。っていうかほしかったんです。

R0010351

スタビレーはドイツの老舗工具メーカーで、Snap-onみたいなテカテカのアメリカ工具がもてはやされる昨今ではむしろ珍しくなってしまった梨地仕上げの表面加工で有名(やっぱ工具はドイツだよなあ。ちなみにPBもドイツはスイスだった)。購入したのは、今年から製造中止になってしまったOpen-Box Type 15というコンビネーションレンチの10mm, 12mm, 13mm, 14mm, 17mm。

Stahlwilleのプレーンなコンビネーションレンチには、大きく分けるとType 13とType 14というのがあって、全長がちがう。Type 14のほうが長い。Type 15は、長いほうのType 14と同じ全長で、オープンエンドの形状が違う。Type 15のオープンエンドは側面が凸曲線に加工されていて、StahlwilleではSoftGRIPと呼んでいた。奥の形状も六角形のボルトヘッドに近いものになっている。写真左がType 15で、右はずいぶん昔にホームセンターで買った安物。

R0010346

一般にオープンエンドのレンチでボルトに強い力をかけると、6面あるうちの2面(もっというと、その2面の片方の対角線のエンド2点だけ)しか接触しないので、ボルトヘッドをなめやすい。そのためコンビネーションレンチは、オープンエンド側で仮締めや早回しをしてメガネ側で強い力をかけるのが正しい使い方。とはいえ、とくにアマチュアだと、オープンエンド側でもそれなりに力をいれたい場合がある。というわけで、Type 15のようなオープンエンドがうれしい。それに側面が凸になっているってことは、口が開いてるってことでもあるわけで、早回しの際にボルトヘッドにひっかけやすいのもうれしい。どこかの通販サイトによると、"The sculptured jaw provides an extra grip on screws and nuts with 25% more static load capacity and 40% more permanent load capacity than standard wrenches. "だって。(残念ながら公式の情報は見つからなかった。)

ところがType 14よりちょっぴり定価が高かったせいか、ドイツでは流行らなかったらしい(お店の人談)。まあ、ドイツの職人はアマチュアにうれしいツールをわざわざ高い値段で買わないってことなのかもしれない。そんなわけで、すでに入手できるのは現在流通しているもののみ。ただ、今のところ在庫処分扱いなので、どうやら安売りしてるっぽい。スタビレーのレンチ5本が9000円以下ってだけで、かなりお買い得。