2006/05/15

Firefox 1.5でいつのまにか日本語の均等割り付けができるようになってるのにきがついた。

むかしは苦労したものだ。http://k16journal.blogspot.com/2005/05/htmlcss2.html

2006/05/14

LaTeX(TeX)で文字列中の文字を置換したい。

cf. Character substitution in TeX
http://hisashim.livejournal.com/276024.html

上記のページにほとんど目的の答えがあるので、これをもう少し汎用にしてみた。
\newcommand{\replacechar}[3]{{\wordbyword{#2}{#3}#1\end }}
\newcommand{\cutoff}[2]{{\relax}}
\def\wordbyword#1#2#3{\ifx#3\end \let\next=\cutoff
\else\ifx#3#1#2%
\else#3%
\fi \let\next=\wordbyword\fi \next{#1}{#2}}
\replacecharの第1引数に文字列、第2引数に置換前の文字、第3引数に置換後の文字を指定する。
いくつか制限がある。判明しているのは以下のとおり。
  • 文字列中のスペースは切り詰められる
  • ほかのコマンドの中で使うには\string\replacechar{foo}{o}{a}などとする必要がある
上記の2番目の制限は、どうやら\defの再帰がトップレベルでしか使えないためっぽい。
同じ理由で、\replacecharを入れ子にして使えない。つまり、文字列中の複数の文字を置換したかったら、同様な方法で新しいマクロを定義する必要がある。たとえば、索引の特殊文字をエスケープするコマンドは、次のようにして作れる。
追記:この例では「"」そのもののエスケープができないので注意。
\newcommand{\indexescape}[1]{{\indexwordbyword#1\end }}
\def\indexwordbyword#1{\ifx#1\end \let\next=\relax
\else\ifx#1{!}"!%
\else\ifx#1{@}"@%
\else\ifx#1{|}"|%
\else#1%
\fi\fi\fi \let\next=\indexwordbyword\fi \next}

\def\myindex#1{\index{\string\indexescape{#1}}}
\myindexの定義に\stringを使っているのも2番目の制限のため。

いちおう、実行例。

replacechar.tex
replacechar.pdf

2006/05/12

sumiiの日記 - callccによる排中律の証明
http://d.hatena.ne.jp/sumii/20060507/1147006438

さらに劣化コピー。Schemeのcall/ccで悪魔の契約書を作ってみる。型についてはまったく無知なので、排中律の証明とは関係ありません。
(昨日は会社でhisashimさんに適当な説明をした気がする。ごめんなさい。)

追記:最初のは間違ってたので差し替えました。
(define able-to-pay? #f)
(define remind-contract #f)

(define (devils-contract init-choice)
(let ((ability able-to-pay?))
((lambda (choice)
(cond ((equal? 'first-answer choice)
(display ""))
((and (equal? 'B choice) ability)
(display "Say any wish!"))
(else
(display "Devil gives you one billion dollars"))))
(call/cc
(lambda (continuation)
(cond ((equal? 'A init-choice)
(display "Devil chooses A"))
((equal? 'B init-choice)
(display "Devil chooses B")))
(set! remind-contract continuation)
(continuation 'first-answer))))))
この挿話は、悪魔にとって選択肢が(A)と(B)しかありえないことがポイントなんだと思う。つまり、(B)じゃなければ(A)。(B)でもないし(A)でもないってことはありえないドライな世界。上のコードだと、最初のcondが契約書に相当するつもり。
で、悪魔は自分が「発話した内容」なんて覚えちゃいない。上のコードでいうと、call/ccの中のcondは覚えちゃいない。あくまでも契約書オンリーなので、後から1億ドル払っても、(B)じゃなかったんだから(A)を履行するってことなんだと思う。

くだんのシナリオは、こんな感じ。
gosh> (devils-contract 'B)
Devil chooses B
gosh> (set! able-to-pay? #t)
#t
gosh> (remind-contract 'B)
Devil gives you one billion dollars

最初の(devils-contract 'B)で悪魔自身は「(B)を選びます」と言っているけど、人間が1億ドル払わなかった時点で実は(A)の契約が成立している。あとから1億円用意(set! able-to-pay? #t)してもだめ(悪魔の契約履行が10年後だったのがひっかけっぽいかも)。

1億円支払い可能な状態で契約し、悪魔が(B)を選択すれば、望みがかなえられるんでしょう。そんな人に悪魔が契約を持ち込むとは思えませんが……
gosh> (set! able-to-pay? #t)
#t
gosh> (devils-contract 'B)
Devil chooses B
gosh> (remind-contract 'B)
Say any wish!

2006/05/10

去年の秋から超朝方を心がけているのだけど、それが可能な体調の期間と困難な体調の期間(ねむ期)がある。ねむ期には生産性のピークが20:00過ぎに訪れるが、それでも非ねむ期における早朝の生産性には程遠い。
ここ一ヶ月にわたって長いねむ期が続いている。ねむ期から抜け出す方法が知りたい。ねむ期→非ねむ期の切り替えは休日の直後に訪れることが経験的にわかっていて、ということは休めばいいのか……

2006/05/08

枝刈りをしながら組み合わせを求めたい。つまり、似たような要素を同一視して、集合の総数を絞りながら組み合わせを求めていきたい。

ふつうなら集合をユニークな要素だけで構成しなおしてから組み合わせを求めればいいんだけど、「ユニーク」の意味によってはそれができない場合もある。
たとえばベクトルからなる集合で、「いずれかの項が同じであれば同一視」のような場合。次のような2次元ベクトルからなる集合Aがあるとして、
A = {(1, 2) (2, 3) (3, 4) (4, 5) (5, 6) (6, 7)}
集合Aからすべての項が異なる3つのベクトルを取り出す組み合わせは、
{(1, 2) (3, 4) (5, 6)}, 
{(1, 2) (3, 4) (6, 7)},
{(1, 2) (4, 5) (6, 7)},
{(2, 3) (4, 5) (6, 7)}
の4つになるだろう。この4つを求めるのに、すべての3要素の組み合わせを求めてから相異なる要素で構成されているものを取り出していると、集合が大きくなるにつれ厄介なことになるのが目に見えている。かといって、集合Aをあらかじめユニークな要素だけで再構成することもできない。

まず、ふつうの組み合わせを求める combinations プロシージャを次のような戦略で考える。

集合をリスト ls とみなし、その要素から n 個の組み合わせをすべて求めるプロシージャ (noraml-combinations ls n) を、次の 1.と 2.の append として作る。
  1. (car ls) と (noraml-combinations (cdr ls) (- n 1)) の cons
  2. (normal-combinations (cdr ls) n)
1.から「(car ls) を先頭の要素に持つ組み合わせ」がすべて得られ、2.で同様の操作をリスト全体にわたって行うつもり。ザ・リストの再帰処理。
(define (normal-combinations ls n)
(cond ((> n (length ls))
'())
((= n 1)
(map list ls))
((> n (+ 1 (length (cdr ls))))
(list ls))
(else
(append
(map (lambda (x) (cons (car ls) x))
(normal-combinations (cdr ls) (- n 1)))
(normal-combinations (cdr ls) n)))))
境界条件がなんか複雑で、本当にこれであってるのかよくわからないのはここだけの話。まあ、とりあえず意図通りの結果にはなるみたい。
gosh> test-set
((1 2) (2 3) (3 4) (4 5) (5 6) (6 7))
gosh> (normal-combinations test-set 3)
((#0=(1 2) #1=(2 3) #2=(3 4)) (#0# #1# #3=(4 5)) (#0# #1# #4=(5 6))
(#0# #1# #5=(6 7)) (#0# #2# #3#) (#0# #2# #4#) (#0# #2# #5#)
(#0# #3# #4#) (#0# #3# #5#) (#0# #4# #5#) (#1# #2# #3#)
(#1# #2# #4#) (#1# #2# #5#) (#1# #3# #4#) (#1# #3# #5#)
(#1# #4# #5#) (#2# #3# #4#) (#2# #3# #5#) (#2# #4# #5#)
(#3# #4# #5#))
枝刈りしながら組み合わせを求めるという本題を達成するには、枝刈りプロシージャ proc を渡して、1.の操作の cdr を proc に変えればいいだろう(2.の部分の cdr はリストの再帰的な操作のためのものなので、proc に変える必要はない)。
(define (trim-combinations ls n proc)
(cond ((> n (length ls))
'())
((= n 1)
(map list ls))
((> (- n 1) (length (proc ls)))
(trim-combinations (cdr ls) n proc))
(else
(append
(map (lambda (x) (cons (car ls) x))
(trim-combinations (proc ls) (- n 1) proc))
(trim-combinations (cdr ls) n proc)))))
枝刈りプロシージャとしては、ベクトルが相異なることを表現する distinct? と、リストとして表した集合から car と相異なる cdr を導く distinct-cdr 用意する。gauche の lset-union は、(use srfi-1) が必要だね。
(define (distinct? v1 v2)
(= (length (lset-union eq? v1 v2))
(+ (length v1) (length v2))))

(define (distinct-cdr ls)
(let R ((tail (cdr ls)))
(cond ((null? tail) '())
((not (distinct? (car ls) (car tail)))
(R (cdr tail)))
(else
(cons (car tail) (R (cdr tail)))))))
実行結果。
gosh> (trim-combinations test-set 3 distinct-cdr)
((#0=(1 2) #1=(3 4) (5 6)) (#0# #1# #2=(6 7)) (#0# #3=(4 5) #2#) ((2 3) #3# #2#))
しかしアレだな。lengthとか使いすぎなので、あまり効率よくないんじゃないか、これ。

2006/05/06

『RailsによるアジャイルWebアプリケーション開発』の制作方式

ここのところ『RailsによるアジャイルWebアプリケーション開発』の制作方式について意見を求められる機会が何回かあったので、もう半年も前のことだけどまとめてみる。

前提として、ふつうのコンピュータ書籍の制作過程には昨日定義した「後戻り困難ポイント」があり、それが原因で誰かが泣いている。誰も泣かないようにするには、昨日愚痴った「後戻り困難ポイント」を埋めてしまえばいい。それには、現在の手作業によるページレイアウトの工程(つまり組版工程)を放棄して、内容に責任を持つべき人間が印刷の直前までハンドリングできるようにすればいい。

『RailsによるアジャイルWebアプリケーション開発』の制作では、この方針を実現すべく、以下のような方法を採用した。
  • 印刷所に納品するデータはフォント埋め込みのPDF
  • そのPDFはLaTeXによる組版データから生成する
  • しかし原稿はLaTeXではないので、原稿をLaTeXに変換するスクリプトを用意する
  • 原稿はSubversionで版管理する
こうやって書き並べると単純すぎる話だけど、これらの方法を採用することによるメリットは強大だった。なにせ、著者(監訳者)や編集者がSubversionからチェックアウトした原稿(≠組版データ)を印刷の直前まで自分で修正でき、その結果が人手を介さずに印刷用の最終的な組版データになるんだから。ようするに、昨日の「後戻り困難ポイント」のうち、組版→編集→執筆の容易な還流が可能になる。あるいは、こういいかえてもいい。これまで組版の工程にかけていた数ヶ月の期間をゼロにできる!

たぶん、こんなのはソフトウェア開発では当たり前のことなんだと思う。ソースコード(原稿)を版管理し、それをデイリービルド(組版)しながら開発(制作)するってだけの話なんだから。ところが現在のコンピュータ書の制作では、コンパイルやビルドに相当する「原稿を組版にする作業」が完全に手作業なため、組版した後で判明した問題を原稿に戻って直したり、直して組版し直した結果をすぐに確認することができない†1

実現にあたっては障壁もいくつかあった。まず、原稿がLaTeXじゃない。また、仮にLaTeXであっても、それだけでは印刷所に安心してデータを渡すことはできない(印刷所の環境で同じようにコンパイルできる保障がない。そのため、印刷所の環境でコンパイルした出力を確認するという作業が不可欠になってしまう)。

印刷所に渡すデータの問題については、PDF/X-1aという業界標準があるので、それに準拠したPDFを生成できれば問題ない。これについては「Debianにotfパッケージをインストールして、dvipdfmxでOpenTypeフォントを埋め込んだPDFを吐き出すまで」を参照。

原稿がLaTeXじゃない問題については、まず原稿がどんな形式だったか示す必要があるだろう。こんな感じのテキストデータだった。
■H1■はじめに
■H2■本書の読み方
本書は初めてRailsに触れる人うんぬん……

★Rubyのコード
本書にはRubyのコードがたくさん出てきます。
しかも予約語は太字に、ダブルクォーテーション内はスラントにしなくちゃなりません。
◆→コード←◆ruby
puts "Hello World"
◆→ここまでコード←◆
ちなみに★で始まってる部分は小さな見出しつきの項目になります。

ここは、また本文に戻ってます。

● 箇条書きもあります。
こんなふうに、なんとなく箇条書きな部分がタブで示されています。
● もうひとつ箇条書き

また本文。

◆→コラム←◆Joeの疑問
枠で囲った記事もあります。「David曰く」「Joeの疑問」のほかに、何も指示のないコラムもあります。
◆→ここまでコラム←◆

1. 箇条書きとは別に
2. 連番もあります

■H3■もっと細かい本書の読み方
脚注もつけなければ◆→訳注 ←◆

■H2■終わりに
おしまい。
これは下訳をお願いした業者さんがよく使っている形式(というか編集指示)を拡張したものだけど、多かれ少なかれどこも似たような「マークアップ」を使っているようだ。見てわかるように、あくまでも人間が手作業で組版するためのコメントみたいな指示書き程度しか施されていない。コンピュータでそのまま処理するにはちょっと厄介な状態といえる(しかも、バリデータなんてないから、けっこういいかげん)。

このような「自然言語+簡易マークアップ」の構造を読み取って適切なLaTeXのスタイルに対応付けるためのフィルタを用意する必要がある。今回はゆるい規則を処理しなければいけないこともあって、後から柔軟にフィルタの仕様を変更できるようなGaucheスクリプトを正月にでっちあげた(私的に余暇を利用して作ったものなので、後日公開する予定。いま見返すと謎な処理が多いけど、なんとか目的の動作は実現している)。

上記の例の変換結果は以下のとおり。
\chapter{はじめに}%

\section{本書の読み方}%

本書は初めてRailsに触れる人うんぬん……%

%

\begin{entry}%
\item[Rubyのコード]
\item 本書にはRubyのコードがたくさん出てきます。
\item しかも予約語は太字に、ダブルクォーテーション内はスラントにしなくちゃなりません。
\begin{ruby}

puts \codesl{"Hello World"}
\end{ruby}%
\item ちなみに★で始まってる部分は小さな見出しつきの項目になります。%
\end{entry}%

%

ここは、また本文に戻ってます。%

%

\begin{myitemize}%
\item 箇条書きもあります。%
こんなふうに、なんとなく箇条書きな部分がタブで示されています。
\item もうひとつ箇条書き%%
\end{myitemize}%

%

また本文。%

%

\begin{column}{J}{の疑問}
枠で囲った記事もあります。「David曰く」「Joeの疑問」のほかに、何も指示のないコラムもあります。
\end{column}%

%

\begin{enumerate}%
\item 箇条書きとは別に%
\item 連番もあります%%
\end{enumerate}%

%

\subsection{もっと細かい本書の読み方}%

脚注もつけなければ\footnote{\kern-.5zw[訳注]}%

%

\section{終わりに}%

おしまい。
このLaTeXの出力から書籍にするには、さらに各要素についてスタイルを定義する必要がある。実はこの作業がいちばん大変なところなんだけど(LaTeXのいい加減な規則や拡張に起因)、これは会社の業務として作成したものなので今のところ公開できない。まあ、LaTeXの泥臭いところが満載なので、実際のところあまり面白くないし。

さて、ここまでは、この方法が従来の方法に比べて万能であることを意図的に強調してきたけれど、現実には適用できないプロジェクトが大半である。著者や制作業者の並々ならない協力が必要なこと、全員がアクセスできるサーバ環境が必要なこと、編集者に現状に対する問題意識が少ないこと、など原因はいろいろある。今回はとくに変換スクリプトをSchemeで作っちゃったりしたので、問題意識のある編集者であっても実際に使ってもらいにくい。

希望はある。こういった問題を解決して汎用性の高いツールにまとめあげる大仕事を身を挺して背負ってくれそうな人がいる。できる限りの協力はしようと思う。



もちろん例外はあって、最初から(商品として妥当な)レイアウトを含めて執筆された(執筆者のローカル環境以外でも同様にコンパイルが通る)LaTeXの原稿があれば、少なくとも執筆者は現在でも最後まで原稿を修正できる。ただし、編集者にLaTeXのスキルがなかったり、印刷所でコンパイルが通らなかったりして、必ずしもうまくいくとは限らない。

2006/05/05

ふつうのコンピュータ書籍がどうやってつくられているか。
  1. 企画
  2. 執筆や翻訳
  3. 編集
  4. 組版
  5. 印刷製本
おわり。

といいたいとこなんだけど、現実はこんなにシンプルじゃない。問題なのは、各ステップがほとんど分裂していること。
  • 編集してから執筆をやり直してもらうことは、よほどのことがない限りできない。
  • 組版してから編集をやり直すことは、実際には頻繁にやらざるをえないんだけど、とても手間と時間がかかる。
  • 書いてはみたけど時間が経ちすぎて市場性がいまいちになっちゃったね。でも企画からやり直すわけには……
  • 当然のことながら、印刷してから誤植が見つかっても直せない。
うー。

上にあげた4つの「後戻り困難ポイント」のうち、最後の1つは物理的にどうしょうもない。どんな製造業にも後戻りできない一歩っていうのがあって、書籍制作の場合にはそのひとつが印刷工程なんだと思う(流通するまでは本当の意味で後戻りできないわけじゃないんだけど)。

で、残りの3つの「後戻り困難ポイント」に直面した場合どうなるか。従来ありがちなのは、順に
  1. 読者が泣く
  2. 制作業者が泣く
  3. 担当者(i.e. 出版社)が泣く
  4. 著者が泣く
この順番に並ぶのは理由がある。まず、「後戻り困難ポイント」に直面するのは制作中の書籍の内容に十分な価値が認められない危惧が生じた場合なわけで、そのまま後戻りできずに流通までいたってしまった書籍の読者が泣く(このケースがほんとに多くていやになる)。
残りは読者が泣いていないケース。つまり、後戻りが不要だった(原稿が完璧で編集も完璧で組版も完璧)か、どっかの時点で困難を乗り越えて後戻りに成功した本である。「後戻りに成功」って書くと、プロジェクトX的な何かっぽくて聞こえがいいけれど、そんなわけはない。誰かがどこかで泣きながら困難な後戻りをやっている。誰がやっているかっていうと、出版社は著者に頭があがらないし、制作業者は出版社に頭があがらないから、推して知るべし。

すっかり愚痴っぽくなってるけど、ようするに現在の書籍制作は前近代的な「誰かが泣く」ソリューションに負っている。もちろん各工程で何も問題がおきなければいいんだけど、文筆のプロではない著者に本業の傍らで執筆してもらい(しかも半ば善意で)、それを一人の編集者が何本も同時にハンドリングし、安い単価でMacオペレータに手作業で組版してもらっている限り、デフォルトで誰かが泣いている。ということは、現在のやり方には何かしら問題がある。

どこに問題があるんだろう。考えられる可能性は、こんなとこ。
  • 紙の本が儲からなすぎ。何事も品質を求めれば金がかかるけど、金をかけようとしないので品質が悪くなり、読者が泣く。あるいは、何とか限られた金額で品質を高めようとして制作業者が泣く。編集者もサービス残業漬けになって泣く。
  • みんな紙が好きすぎ。とにかく紙に印刷されたものベースでしか制作が進まない。内容に責任を負うべき人間が制作にかかわる唯一の方法は、紙へ手作業で赤字を書き入れること。それをもとに、内容には関与しない人間が、やはり手作業でちまちまとデータを修正する。赤書きした本人が修正結果を確認できるのは数週間後だったりする。修正作業者が内容を理解しているわけではないので、その作業が新たな問題を生むことも少なくない。
  • 制作技術の進歩がなさすぎ。ページレイアウトを作るのに、いまだに植字工が活版を組んでいるのと原理的に同じ作業をコンピュータを使って手作業でやってる。一度組んでしまったものをスケジュールを崩さずに直すのは不可能。あとどうしょうもなくバカバカしいのは、節番号や図暗号の連番をふったり、ページ番号を参照したり、索引のページを解決したりするのが、全部手作業なこと。そんなのLaTeXやMS Wordでも自動でできるって(DTPソフトによってはできるものもあるけど、オペレータの数が限られていて一般には利用されていないというオチ。このへんも手作業な世界観が支配的で情けなくなるところ)。
というわけで、企画するまではともかく、そこから先の印刷直前までの工程は一種のバクチなのが実情。

ではどうするか。いちばんキモなのは、内容に責任を持つ人間が最終的なページレイアウトまでをハンドリングできるようにすること。紙に赤字で修正指示を出して……という他人任せな方法は極力回避する。これには2つメリットがある。
  • ありえないミスがなくなる。赤字の修正指示は字の汚い人間にとって苦痛なだけでなくリスキーでもある。それを見てデータを直す人間が内容を理解していれば対応できるけど、専門書でそんなことは期待できないわけで。とくに数式をよろしく対応してもらうのは絶望的
  • 制作期間を短縮できる。紙をやりとりするのは時間の無駄。
これを実現するには、「最終的なページレイアウト」とか、そういう夢見心地な発想をあきらめること。この発想の背景には、内容とレイアウトは別物という意識がある。たぶんこの意識はページレイアウトをする側のものだと思う。確かに本当に凝ったレイアウトを扱うにはそれだけを見る人間が必要だけど、そんなのは「伝票をチェックするためだけに人を雇う」というのと同じ発想で、それだけの規模がある業務なりプロジェクトなりでなければ無駄でしかない。(ちなみにここでレイアウトって言ってるのはデザインのことじゃない。)

で、ページレイアウトって、正直Webページ程度の表現力があれば事足りるものが多い。Webページであれば、公開する直前まで執筆してる人間が内容を修正し、それにCSSなりでスタイルを当てれば十分なコンテンツになる。しかも、執筆している人間に公開の直前まで許されている修正は、「てにおは」レベルのものじゃない。文章の階層構造はもちろん、説明の順番や図の配置まで、全部修正できる。どうして書籍の制作ではWebページのようにぎりぎりまで原稿を修正することができないのだろう。
Webブラウザと紙ではメディアとしての性格が違うという人も(DTPによる書籍制作にかかわってきた人のなかには)いるだろうけど、それは説得力がない。LaTeXとか、20年前からふつうに同じようなことができてたわけで、紙の制作に限って技術的な制限があるなんていうのはDTPソフト会社にだまされているだけだ。

2006/04/25

今日の一行 2006-04-20 [quiz] 部分木の格上げ
http://oss.timedia.co.jp/index.fcgi/kahua-web/show/ossz/oneline/2006-04-20

「述語と木を与えて,述語を満すラベルの付いた部分木をその親の直ぐの弟にする関数を書け.」という問題。またまた出遅れ気味の回答。この翌日で、逆に部分木を格下げする問題も出題されているけど、こちらはカテゴリがquizではないらしいので手をつけないことにしよう。この問題だけで力尽きたともいう。
(define (lookup subtree pred)
(let lookup-for-suns ((suns (cdr subtree)))
(cond ((null? suns) '())
((pred (caar suns)) (car suns))
(else
(lookup-for-suns (cdr suns))))))

(define (include? subtree pred)
(let check-for-suns ((suns (cdr subtree)))
(cond ((null? suns) #f)
((pred (caar suns)) #t)
(else
(check-for-suns (cdr suns))))))

(define (without-grandchild? tree)
(or (null? (cdr tree))
(let without-children? ((suns (cdr tree)))
(cond ((null? suns) #t)
((null? (cdr (car suns)))
(without-children? (cdr suns)))
(else #f)))))

(define (extract tree pred)
(cond ((null? tree) '())
((pred (caar tree))
(extract (cdr tree) pred))
(else
(cons (car tree)
(extract (cdr tree) pred)))))

(define (rankup tree pred)
(if (without-grandchild? tree)
tree
(cons (car tree)
(let rankup-for-suns ((suns (cdr tree)))
(cond ((null? suns) '())
((include? (car suns) pred)
(cons
(cons (caar suns)
(extract (cdar suns) pred))
(cons (lookup (car suns) pred)
(rankup-for-suns (cdr suns)))))
(else
(cons (rankup (car suns) pred)
(rankup-for-suns (cdr suns)))))))))

(define test-tree
(list 'A (list 'B (list 'F)
(list 'G (list 'L)
(list 'M)))
(list 'C (list 'H)
(list 'I (list 'N)
(list 'O (list 'P)
(list 'Q)))
(list 'J))
(list 'D)
(list 'E (list 'K))))

(define eq-I? (lambda (x) (eq? 'I x)))

gosh> test-tree
(A (B (F) (G (L) (M))) (C (H) (I (N) (O (P) (Q))) (J)) (D) (E (K)))
gosh> (rankup test-tree eq-I?)
(A (B (F) (G (L) (M))) (C (H) (J)) (I (N) (O (P) (Q))) (D) (E (K)))

いかにも、SICPの前半を読んでいる最中です、という雰囲気のただよう回答にみえる。きをあつかうのは大変だ。
今日も歯医者。消毒だけだと思って気を抜いていたら、また注射があった。でも、昨晩心配していたような痛みもなく、本当によかった。この後は、一ヵ月くらいそのまま歯茎が再生するのをまって、ブリッジかなにかするらしい。歯茎が再生したらこのままでもいいんだけど、それはダメなんだろうな……

2006/04/24

先週、奥様が自分の歯医者にいくというのでくっついていって検診してもらったら、レントゲンをとられて奥歯を一本抜くことになった。で、いまさっき抜いてきた。小学校のころいれた銀歯で、ずいぶん前からぐらついていたのは自分でも知ってたんだけど、こういうのってどうしても放置しちゃう。結局、長年の間にクラウンの中はすっかりぼろぼろになっていた。レントゲン写真を見て、自分から「抜いてください」とお願いしたくなるくらい。へたに周りの歯がしっかりしているものだから、かえって痛々しさが目立つ。

歯を抜くのは初めてなので、ここ一週間は夜も眠れないくらいびくついていた。だいたい、人間が痛みに耐えるときは歯をくいしばるものなのに、歯を抜くってことはそれができない。麻酔をかければ痛くないっていうけど、その麻酔の注射を歯茎に射すわけじゃん。麻酔されるまで診察台の上で終始手をきつく握り合わせていたら、先生に「そんなに心配しなくて大丈夫ですよ」といわれてしまった。実際、ほとんど痛くなかった。歯を抜く作業も手際がよくて、すーっと何かが抜けていく感覚だけ。ここ一週間、歯を抜く痛みのイメージトレーニングをひそかに繰り返していたので、脳内で大量のエンドルフィンが生成されていただけかもしれない。もちろん、先生の腕もいいんだと思う。彼の一連の作業の流れを見ていればわかる。抜いた後に再度レントゲン撮影して状態を確認するのも好感がもてる。でも、本当に痛み出すのは麻酔が切れる今晩からだっていうしなあ。幸いなのは、頼みの綱として痛み止めと化膿止めをもらったこと。しかも、ロキソニンとケフラールだった。これならうちに山ほどあるので、使い切ってもちょっと安心。

2006/04/21

小島麻由美が好きだ。もう、3月に出た6枚目のアルバムが、すごくいい。

スウィンギン・キャラバン
http://www.amazon.co.jp/exec/obidos/ASIN/B000EAV942/

小島麻由美を聞いたことのない人には、2000年のベストがお勧め。

Me And My Monkey On the Moon�Singles and Outtakes�
http://www.amazon.co.jp/exec/obidos/ASIN/B00005HP68/


このベストの後に出た4枚目は個人的に肌に合わない。この6枚目にして、ようやく戻ってきてくれたみたい。
4枚目は、世間的な評価はいいようだけど、どうにもオサレ風なほんわかエフェクトが強くて好きになれない。録音も不用意に音を詰め込みすぎ。歌詞も斜めな視線を気取りました的だったし。もっとこう、かわいくって異次元な小島麻由美の歌を、モヤモヤしていないソリッドな音で聞きたいわけよ。ひたすらショートケーキとか連呼してほしいわけよ。
6枚目にいたって、ようやくそういう雰囲気に戻ってきてくれた。手放しでよろこばしい。脳内には「らすーとのつーもりでー」がリピートされまくり、チョコレートがとけまくり、トルココーヒーが渦巻いている。
ただ、初期のころに比べて「うまさ」を前に出してきてるのは、やっぱり進化だと思うしかないのかなあ。いまは、「うまさ」が「芸風」を犠牲にしていない、そういうぎりぎりのところにいる気がする。そのぎりぎり感が、このアルバムを傑作たらしめているんだとも思う。でもやっぱり引っかかるんだよなあ。なぜか一曲目にして「また明日ね!」といわれてしまうアルバムの構成とか、初期のころの特徴といっていいと思う「妄想のかたまりな歌詞」を意識的に創作しているように見えてしまうところとか。

社内の雑談で「小島麻由美なんてしらねえよ」と言われてしまったので勢いで書いてはみたけれど、読み返すと批判に見えちゃうな。でも違うよ。とにかく小島麻由美が大好きだってことで。


どうでもいいけど、「トルココーヒー」を聞いていると藤子・F・不二雄の短編の「アン子、大いに怒る」の一場面が思い浮かんじゃう。ちょうどはまっている最中っていうのもあるけど、それにしたってあそこで飲んでいるのはコーヒーじゃなくて紅茶だ。でも、外国土産のいかがわしい飲み物をきわめて日常な場面で飲むっていうところは通じていて、結局そういう「日常→妄想」の境界付近が自分は好きなんだろうと思う。

2006/04/19

一区切りついたので、ここ数日たまりまくった Bloglines を眺めていたら、また面白げな問題が話題になっている。例によって乗り遅れ気味。
2回作用させると符合が変わるという性質は、虚数とか、三角関数の微分とか、回転行列( (0 -1 \\ 1 0) )とかがあるけど、どれも実数から実数への関数ではない。というわけで、こんないんちきしか思いつきません。
x = sinθ
f(x) = (d/dθ) x

=>

f(x) = cosθ
f(f(x)) = -sinθ
= -x(!?)

こんなのは関数の定義とはいえないわけで。

2006/04/13

昨日、Red Bull という話題の清涼飲料水を試しに飲んでみたら、ほんとに眠くならない。それで、一日がんばって仕事をしたら、今朝になって風邪の初期症状が。2つの説明。
  • Red Bull は一時的に体力をブーストするだけであり、人間の体力には絶対的な限界があるので、必ずあとでツケを支払うことになる
  • Red Bull は本当に体力を増強する。本当は昨日から風邪だったのに、昨日は Red Bull のおかげでなんとかがんばれた
論理の錯誤は無視して、今日のところはもう一本 Red Bull を飲んでがんばらなければならない。
 

2006/04/07

昼休みの明けの妥協案。けっきょくカウンタみたいなものを使うことにした。あと、car部が巡回リストを含む場合はチェックできない(これをなんとかしようと考えてたら、もうこんな時間!)。あくまでも、「cdrを追っていくようなプロシージャが停止しないリスト」かどうかを調べるってことで(つまり、今朝の z みたいなものは引っかからない)。
(define (cdr-cycle? x)
(if (not (pair? (cdr x)))
#f
(let R ((x x) (y (cdr x)) (c 0))
(cond ((null? y) #f)
((eq? x y) #t)
((< 0 c) (R (cdr x) y (- c 1)))
(else (R x (cdr y) (+ c 1)))))))
gosh> x
(0 . #0=(1 2 . #0#))
gosh> (cdr-cycle? x)
#t
gosh> y
(0 0 . #0=(1 2 . #0#))
gosh> (cdr-cycle? y)
#t
gosh> z
((0 . #0=(1 2 . #0#)) . 4)
gosh> (cdr-cycle? z)
#f
突っ込みありがとうございます。>Anonymous
サブリストが巡回しているケースということであれば、昨日の「全巡回リストチェックルーチン」を car と cdr についてチェックするように修正すれば大丈夫そうだけど、はたして問題はそこなんだろうかという不安が残る。
;; ex. 3.19
(define (cycle? x)
(define (whole-cycle? sub)
(if (or (null? sub) (not (pair? sub)))
#f
(let R ((y (cdr sub)))
(cond ((null? y) #f)
((eq? sub y) #t)
(else (R (cdr y)))))))
(if (or (null? x) (not (pair? x)))
#f
(or (whole-cycle? (car x))
(whole-cycle? (cdr x)))))

gosh> x
(0 . #0=(1 2 . #0#))
gosh> (cycle? x)
#t

サブリストについては再帰的にチェックしていないので、こうすればまた同じ問題に悩まされる。
gosh> x
(0 . #0=(1 2 . #0#))
gosh> (define z (cons x 4))
((0 . #0=(1 2 . #0#)) . 4)
gosh> (cycle? z)
...

論理的には、こういう再帰的なチェックをすれば解決するのだと思う。or の評価順序の問題があるので、これはもっとどうしょうもなく停止しないけど。
(define (cycle? x)
(define (whole-cycle? sub)
(if (or (null? sub) (not (pair? sub)))
#f
(let R ((y (cdr sub)))
(cond ((null? y) #f)
((eq? sub y) #t)
(else (R (cdr y)))))))
(if (or (null? x) (not (pair? x)))
#f
(or (cycle? (car x)) (whole-cycle? (car x))
(cycle? (cdr x)) (whole-cycle? (cdr x)))))

どうすっかな。根本的な考え方を変更する必要があるのかも。

研究者にとっては問題を解くことじゃなく問題を見つけることが重要な仕事だって、どっかで聞いた記憶がある。僕は研究者ではないけれど、ほかの仕事の多くでも、問題を見つけることは積極的に評価されるべきだと思う。
というわけで、重ねてありがとうございます。>Anonymous

あー、なんか朝からハイだ。

どうでもいい妄想して勝手に怒りが込み上げてきた。あえて猥褻な言葉を使ってお茶を濁すと、問題を見つけることがビジネスモデルで、それを解くために投入する時間とコストと人材がビジネスポリシー。見つけた問題がセンスない&&周回遅れで、しかもその解決方法が的外れなんだから、誰とは言わないけど終わってる。まったく。

2006/04/06

かと思うと、exercise 3.19 のように、(This requires a very clever idea) と補足されているような「とんち問題」もある。問題は、巡回リストかどうか判定するプロシージャを set! とか使わないで書け、というもの。

clever idea がなくても、無限集合の重要な性質を知っていればすぐに思い付く方法がある。その性質というのは、「無限集合は、その部分集合と濃度が等しい」というもの。集合の濃度っていうのは、要素の個数くらいの意味。「無限の個数ってなんだよ」って開き直ったら負けで、「一部分だけ取り出してきたのに元と同じくらいたくさん詰まっているのを無限っていうことにしようぜ、逆に」というのが数学なんだと思う(適当)。なんにせよ、clever idea があるとしたら、それは集合論を思い付いた Cantor のものだ。

とにかく、巡回リストも無限集合みたいなもんなので、その一部分が元のリストと同じだけの要素を持っているっていう性質がある。とくに巡回リストの場合は、cdr を取っていくと、そのうち元のリストと同一(eq? の意味で)になる。必ず。

そこで、こう書ける。
;; ex. 3.19
(define (cycle? x)
(if (null? (cdr x))
#f
(let R ((y (cdr x)))
(cond ((null? y) #f)
((eq? x y) #t)
(else (R (cdr y)))))))

gosh> x
#0=(a b c . #0#)
gosh> (cycle? x)
#t


昨日も今日も定時で帰ってきたので、なんかハイだ。
ページ数かぞえ間違えた。まだ半分いってないや。ようやく3.3節に入ったところ。

実は、3章に入ってしばらく、いまいち面白くなかった。主な原因は、set! の使い方を覚えましょう的な雰囲気にあると思う。語弊のない言い方をすると、set! を通して Scheme を深く理解するきっかけをつかむ、っていうところかなあ。ここから先の解説は、関数型プログラミングというより、「コンピュータから見た(Scheme の)プログラム」なのかもしれない。ああ、そもそもそういう趣旨の書名だったか。

もしかしたら、関数型プログラミングにだけ興味がある人は、2章まで読めば十分なのかもしれない。

もちろん、まったく面白くないわけではない。当たり前だけど。ようするに自分が知らないことを気づかせてくれれば面白いので、たとえば exercise 3.16~3.17 は、リストの本当の姿、つまり cons セルとしての姿を実感させてくれて面白い。

リスト x = (a b c) には、いくつの cons セルがあるか。SICPでは、まずナイーブな方法が例示されている。
(define (count-pairs x)
(if (not (pair? x))
0
(+ (count-pairs (car x))
(count-pairs (cdr x))
1)))
(define x (list 'a 'b 'c))
gosh> (count-pairs x)
3

これの何が問題かっていうと、リスト内の cons セルを示している car や cdr がある場合に意図した答えにならないこと。
gosh> (set-car! x (cdr x))
gosh> (count-pairs x)
5

自分は、絵を書かないとわからなかった。最初、x はこうなっている。!は、下向き矢印↓のつもり。
x-->|*|*|-->|*|*|-->|*|/|
! ! !
|a| |b| |c|

たしかに、consセルが3つある。ここで、(set-car! x (cdr x)) すると、x のリスト表記は ((b c) b c) になる。絵で書くと、こう。
     ________
| !
x-->|*|*|-->|*|*|-->|*|/|
! !
|b| |c|

これを count-pairs で調べると、2個目の cons セルより後ろを2回数えてしまうので、実際の cons セルは 3 つのままなのに結果が5になる。ちなみに、消えた a については忘れていい。キーワードはガーベジコレクションらしい。

この問題を回避する count-pairs を書けというのが exercise 3.17。同じやつを2回数えなければいいだけなんだけど、「同じ」って何?という哲学的な命題と対峙しなければいけない。実際には哲学ではないので、eq? の本当の意味を理解しているかどうかがポイントになるんだと思う。僕の回答。
;; ex. 3.17
(define (count-pairs x)
(define aux-pairs '())
(define (member-eq? c ls)
(cond ((or (null? ls) (null? (cdr ls)) (null? c)) #f)
((eq? c (car ls)) #t)
(else
(member-eq? c (cdr ls)))))
(define (aux-count x)
(cond ((not (pair? x))
'())
((member-eq? x aux-pairs)
'())
(else
(set! aux-pairs (cons x aux-pairs))
(append (aux-count (car x))
(aux-count (cdr x))))))
(aux-count x)
(length aux-pairs))

gosh> (count-pairs x)
3

こんな小さな問題で、やたらにいろいろなことが示唆されているので、やめられない。
これなら、(set-cdr! (cddr x) x) みたいな循環しているリストに対しても、正しい答えが得られる。一見すると終わりがないものにケリをつける方法っていうのは、それだけで魔法みたいで、やっぱりやめられない。

ちなみにこんなことをわざわざ書いているのは、独習で不足しがちな「説明してみることで自分の理解度を確認する」という作業を補っているだけです。Webって本当に便利ですね。したがって、あらゆる記事は、きちんと理解した人間による解説ではありません。

2006/04/05

SICP がブームらしい。ということをsumiiさんの日記で確認した。職業がら、その手の「ブーム」には気づいてなきゃいけないんだけど、自分の中でなんとなくブームであることを否定していたような気がする。にしても、いつくらいからブームなんだろう。

自分は、5年くらい前に存在を知ってから「いつかきちんと読んでみたい」と断続的に思いつつだらだらと過ごし、いろいろあって去年の11月頃から一人でねちねちと問題を解き進めている。ちょうどそのころにクレジットの契約ができるようになって amazon で原書を注文することが物理的に可能になった、というのも大きい。

帆船模型を作るみたいに、ゆっくり、とにかく手を抜かずにやってるので、遅い。索引を除くページ数でようやく半分を越えた。内容を考えると、この先のほうが時間がかかるだろうから、今年中には読み終らないんじゃないかなあ。

ここまで来たので、べつにブームが来ようがブームが去ろうが、静かに勉強し続ける。

sumiiさんの一連の記事については、その影響で「ブーム」が去るような気がしないでもないし、何より「次」の教材を示してくれているので、大変うれしい。なんていうか、世の中には勉強することに飢えている非学生な人間が少なからずいると思うので、(信頼できそうな)研究者の方によるこの手の書き込みはとても助かります。

2006/04/04

土曜の朝から原因不明の発熱で寝込んでしまった。正確に言うと、土曜の昼前からか。その日の早朝は元気だった。土曜日はタワーレコードまで出かけて行ってCDを買うつもりだったのに。
ようやく熱がひいてきたので、土曜日にできなかったことを片付けることにした。とはいえ、あんまり食べてなくて体力がなく外出はできないので、Amazon なんだけど。
自分にとってタワーレコードは、新宿店がCDを漁るのに魅力的な場所なのであって、だからタワーレコードのWebで買物をしたいわけではない。

2006/03/31

ここのところ、職業倫理について考えることが多い。これまでは、考えるものではなく、事あるごとに意識するものだった。職業倫理にもとる行為は、しないのが当たり前。金もらってる以上、顧客やビジネスパートナー(いまどき、どっちも Buzz っぽい)の利益になる行動をしろ。信頼(これも Buzz っぽい)は裏切るな。自分の仕事に誇り(やっぱり Buzz っぽい)を持て。

なんか違うと感じるのは、職業倫理とされているものは、どれも「くいぶち」にあぶれないための知恵でしかないんじゃないかってとこだ。それはそれでいいし、必要だし、大切だと思うけど、はたらくってのは所詮「くいぶち」なのか? 「食ってけなかったらどうする。くいぶち上等」のようなコメントは受け付けません。「はたらく=くいぶち」は、極論すれば「第三次産業なんてやめちまえ」に聞こえるから。なんで書籍みたいなモノが僕の「くいぶち」に転化されるのさ。そのモノが誰かにとって「くいぶち」になるから。そんなことは19世紀の時点ですでに常識。いまは21世紀。もうちょっと進化してるはず。っていうか、進化しててくれないと困る。いまさら野麦峠は越えたくないって。

で、職業倫理について考えてみるわけだけど、考えれば考えるほど、これが実は危険思想なんじゃないかと思えてくる。もうちょっと限定すると、職業倫理ドリブンであることの危険性。

たとえば、「エンドユーザのため」という台詞は聞こえがいいけれど、それは「家族のため」とか「上司のため」とか「会社のため」とか「お国のため」っていうのと何が違うのか。いずれの場合も根っこにあるのは保身だし、くいぶちなんじゃないかと。批判はしない。ただ、「はたらく」の根っこにあるのが「○○のため」っていうのは、素朴に考えて寂しいだけじゃなく、いきつくところは野麦峠かもしれなくって鬱。

あるいは、本当に自分の仕事に誇りを持つべきなのか。仕事に関係なく、自分自身に誇りを持つべきじゃないの?

じゃあ、何を「はたらく」の背景に抱けばいいのか。まず信じていいのは、技術だと思う。どんな「はたらく」でも、技術がなければ役に立たない。もちろん、ここでいう技術はテクノロジーではない。「はたらく」によっては、無作為な人間とのコミュニケーション能力みたいなのが重要かもしれない。もうひとつはセンスだろう。本来は技術と切っても切り離せないものだけど。

となると、どうすれば技術とセンスを取得できるかが問題になる。暫定的な自分の答えは、「各自が好きなことを続ける」。好き→続ける→技術とセンスがついてくる、という進研ゼミのような理屈はわかりやすいと思う。それに、好きじゃないことを「仕事だから」って開き直って続けるのはやめようよ。それは不幸だから。

この答えは、実は何も言っていないに等しいし、好きじゃない仕事に就かざるを得ない人のことを考えていないことも十分に自覚している。あと、自分のことを棚に上げていることも自覚している。そもそも、好きなことっていうのがよくわかっていない。僕は、好きなことがなんだかずっとわからない(いまだにかなりあやふや)。だから、スポーツ選手とかミュージシャンのような、好きなことがわかりやすい「はたらく」がうらやましい。それが続けられるほど好きな人がうらやましい。僕の話はどうでもいいので終了。

2006/03/26

いまごろ気づいた面白いクイズ。

AA折れ線グラフ(nobsun)
http://oss.timedia.co.jp/index.fcgi/kahua-web/show/ossz/oneline/2006-03-14

あまり悩まないでさくっと書いてみることにした。各行で出力する切片たちを割り出して、上の行から順番に書いていくだけなので、Cでもいいじゃんと言われたらそれまでという悲しさ。自分としては、各行の割り出し方が数値的なところがお気に入りなんだけど。
そういえば K&R にも、垂直方向のヒストグラムを出力させる問題があった気がする。横のものを縦にするという点では近いものがある。ない?
;; aa-graf.scm

(define (aa-graf RFC)
(let ((aas (aas RFC))
(alts (altitudes RFC)))
(let draw ((alt (apply max alts)))
(graf-at alt alts aas)
(if (> alt (apply min alts))
(draw (- alt 1))))))

(define (graf-at alt alts aas)
(print (list->string
(map (lambda (x y)
(if (eq? x alt)
y
#\space))
alts aas))))

(define (aas RFC)
(map (lambda (x)
(cond ((eq? x #\R) #\/)
((eq? x #\F) #\\)
((eq? x #\C) #\_)))
(string->list RFC)))

(define (altitudes RFC)
(map (lambda (pair)
(min (car pair) (cdr pair)))
(let R
((s 0)
(ls (map (lambda (x)
(cond ((eq? x #\R) 1)
((eq? x #\F) -1)
((eq? x #\C) 0)))
(string->list RFC))))
(if (null? ls)
'()
(cons (cons s (+ s (car ls)))
(R (+ s (car ls)) (cdr ls)))))))
gosh> (aa-graf "RCRFCRFFCCRFFRRCRRCCFRFRFF")
__
/ \/\/\
_/\_/\ _/ / \__/\ /
\/

それじゃあほかの人たちのエレガントな解答を見てみよう、と思ったんだけど、いきなり shiro さんが何をやってるんだか分からない……。つーか、自分が比較的プリミティブな Scheme の機能しか知らないのがいけない。てなことを書くと、リファレンスマニュアルを調べろと怒られそうだけど、まだまだ調べるよりも作るほうが楽しいお年頃(関数年齢)。プログラミングを独習するには10年かかるからしょうがないか。

2006/03/23

木曜洋画劇場でスティーブン・セガールをやっているとつい最後まで真剣に見てしまう症候群

2006/03/22

ようやく第2章まですべての問題が終わった。
;; ex. 2.97
(define ex-2-97-p1 (make-poly-with-dence 'x '(1 1)))
(define ex-2-97-p2 (make-poly-with-dence 'x '(-1 0 0 1)))
(define ex-2-97-p3 (make-poly-with-dence 'x '(0 1)))
(define ex-2-97-p4 (make-poly-with-dence 'x '(-1 0 1)))
(define ex-2-97-rp1 (make-rational-number ex-2-97-p1 ex-2-97-p2))
(define ex-2-97-rp2 (make-rational-number ex-2-97-p3 ex-2-97-p4))
gosh> (print ex-2-97-rp1)
(x + x^0)/(x^3 + -x^0)
gosh> (print ex-2-97-rp2)
(x)/(x^2 + -x^0)
gosh> (print (add ex-2-97-rp1 ex-2-97-rp2))
(-x^3 + -2x^2 + -3x + -x^0)/(-x^4 + -x^3 + x + x^0)

Mathematica をはじめて使ったとき以来の感動。なにせ、SICP片手とはいえ自分でコードを書き、まがりなりにも中で何が起きているかを把握しているんだから。

それでもやっぱりはずかしい、ぐちゃぐちゃコードたち。主に自分のためのバックアップ用。いつの日かもう一度書き直す。

symbolic-algebra-generic.scm

arithmetic-tower.scm
install-sparse-polynomial.scm
install-dence-polynomial.scm
日帰りで別所温泉に行ってきた。長野新幹線で上田まで1時間半、そこから上田電鉄別所線に乗り継いで30分くらいで別所温泉駅に到着する。関東甲信越にはこの手のローカル線がけっこう残っていてうれしい。

DSC_0017 別所線。さすがにこの車両は走ってない

空がきれいなのは、朝の9時だからだけではないと思う。

DSC_0014 塩田の車窓から

別所温泉には立ち寄りの公衆浴湯が何箇所かある。今回は大湯と石湯に入った。いずれも150円で、大湯のほうが硫黄臭が強くて温泉っぽい。でもこれは、湯が浴槽に到達するまでの距離の違いだろう。いずれも、かけ流しではなく循環式。まあ、別に循環式でもいいんだよ、楽しめれば。

実際にこの土地にくるまで知らなかったんだけど、付近には鎌倉~室町のころの遺産が多い。とくに三重塔がやたらにある。日本史には疎いんだけど塔、それも三層のやつには興味があるので、なかでも正八角形が魅力的な安楽寺の三重塔と、未完成が魅力的な前山寺の三重塔に行ってみた。どちらの寺も、塔の周りはふつうの分譲墓地で、お彼岸のお参りに来ている人がちらほらいる。一般の墓地の真ん中に国宝があるのは不思議だと奥様にいったら、京都や東京と違ってこのあたりの寺を維持するには檀家からの収益が重要なんだろうとのこと。確かにそうかもしれない。

DSC_0049 安楽寺三重塔。四層に見えるのは1階に屋根が2枚あるから

散策には別所温泉駅で自転車を借りた。とくに前山寺は山の上にあって、ふつうの自転車(サドル低い)がつらい。寺の前で胡桃を売っていたおばちゃんが「どこから自転車?」と聞くので「別所温泉駅」と答えると、あきれられた。自転車が最強の東京だと 3 km くらいどうってことないけど、自家用車中心の山間ではアホに見えるんだろう。

DSC_0055 前山寺は右手の山の上

別所温泉駅で自転車を借りる人の大半は、この自転車でどこにいくんだろう。

2006/03/18

姉さんとしたう人の一人が、今日、これまで彼女が属した共同体を離れて別な仕事を初めるというので、お祝いをした。おめでとうございます。あなたは、ほかで仕事をしたほうがいいと思うよ。これからも遊んでね。


じっと手を見る。

2006/03/11

ひさしぶりに電車にのったら、どっかの塾の広告が「日本の小学生は 9×9 までだけどインドの小学生は 19×19」っていってる。これは趣旨としては「もっとつめこもうぜ」であり、「詰め込みのお手伝いをさせていただくので費用をたっぷりお支払いください」だよなあ。ゆとり教育の見直しバンザイ……なわけないだろ

実は 19×19 の暗算は、思うほどむつかしくない。中学生以上なら、こんなふうにできる。
19×19 = (20 - 1)2 
= 202 - 2×20×1 + 12

ようするに、19 を 20-1 だと思って、誰もが中学校で詰め込まれたはずの文字式の展開をしただけ。
(a - b)2 = a2 - 2ab + b2

202 - 2×20×1 + 12 には、九九の延長で対応できる掛け算しかなくて、結局 400-39 になる。19×19 を脳内筆算するのはしんどいけど、400-39 なら暗算できる範囲だと思う。400-39 にもっていくまでに多少の脳内レジスタは必要だけど、常態でそれくらいのレジスタを確保できない脳みそが 19×19 を暗記するのはどのみち無理ですから。

つまり2桁の掛け算を九九のように暗記させる必要はない。むしろ積極的に暗記させないほうがいいかもしれない。どうせ詰め込むなら、文字式の展開とか因数分解の公式を小学校で詰め込んで、こんなふうに応用できることを教えてやってください。「あげるなら魚じゃなく釣竿」ってやつね。

2006/03/07

いま質問されて思い出したけど、dvipdfmx では pstricks が使えない。っていうか、\special 環境が使えない。

Debianにotfパッケージをインストールして、dvipdfmxでOpenTypeフォントを埋め込んだPDFを吐き出すまで


前提1


dvipdfmxのインストールまでは、以下のページで完了しているものとする。

* Debian GNU/Linux (Sarge)でのLaTeX導入備忘録
http://cise.edu.mie-u.ac.jp/~okumura/texwiki/?Linux%2FDebian

ちなみに、debianでLaTeXを使うときに参考にできるURLは、事実上ここしかないと思う(ここ以外の情報は、申し訳ないけど情報が断片的すぎて使えなかった)。

前提2


仮想フォントは使わない。つまり、あくまでも正規のOpenTypeフォントのライセンスを持っている人が、それを使ってDebianでフォント埋め込みのPDFを生成することを目標とする。つまり、ぶっちゃけほとんどの人には役に立たない情報。

otfパッケージのインストール


まず、otfパッケージを導入する。以下からotfパッケージのソースを取得して、添付されているシェルスクリプト(makeotf)でインストールする。

* Open Type Font用VF
http://psitau.at.infoseek.co.jp/otf.html

なお、ソースのreadmeには「古いバージョンのovp2ovfやopl2ofmが必要」とあるが、仮想フォントを使わないのであれば不要。ここでも、あえて古いバージョンを探して入れるようなことは(パッケージ管理上も問題があると思うので)しない。シェルスクリプトそのものは、標準でplatexを入れた場合にインストールされるバージョンでも支障はないっぽい。

OpenTypeフォントのインストール


/usr/share/texmf/fonts/otf および/usr/share/texmf/dvipdfm/Fonts みたいなディレクトリを作って、そこにフォントデータをおく。その後、update-texmf(またはmktexlsr)を実行する。

この時点で、プリアンブルで\usepackage{otf}としたLaTeXのソースはコンパイルできるはず。しかし、dvipdfmxを実行しても、
[1kpathsea: Running mktexpk --mfmode ……
みたいなエラーメッセージが出るはず。

dvipdfmxでOpenTypeフォントを使えるようにする


/etc/texmf/dvipdfm/dvipdfmx.cfg の最後の行に、
f hiraginox.map
などと書く。hiraginox.mapのところは、使用するOpenTypeフォントに合わせて、kozukax.mapやmorisawax.mapを指定する。
なお、hiraginox.map などの本体は /usr/share/texmf/dvipdfm/config にある(otfパッケージを入れる際にインストールされる)。TeXの常識だとこのディレクトリに dvipdfmx.cfg を置くみたい(実際ここにも dvipdfmx.cfg があったりするかもしれないけれど)。でも Debian では、/etc/texmf/dvipdfm/dvipdfmx.cfg を上記のように修正しないと、kpathsea に文句を言われ続ける。

使う


プリアンブルに\usepackage{otf}を指定して platex と dvipdfmx を実行すればいい。
自分はプリアンブルにこんな感じに指定して使っている。
\usepackage{type1cm}
\usepackage[T1]{fontenc}
\usepackage[scaled]{helvet}
\usepackage[deluxe]{otf}
\renewcommand{\rmdefault}{ppl}
\renewcommand{\sfdefault}{phv}
\renewcommand{\ttdefault}{pcr}

[おまけ]PDF/X-1にする


印刷所に安心して入稿するには、PDF/X-1 で検証された PDF にすべき。でも、これは Adobe 社謹製の何かを使わないと実現できないんじゃないかしら。つまり、Debian だけではできなくて、Adobe Acrobat Professional 7.0 がインストールされた Win/Mac マシンで行わなければいけないと思われる。

基本的には、まず上記の方法で生成した PDF ファイルを Adobe Acrobat Professional 7.0 で開き、PS で保存し直す。それから、その PS ファイルを Adobe Acrobat Distiller 7.0 で PDF/X-1 に変換すればよい。

ただし、上述した方法で OpenType フォントを埋め込んだ PDF を生成しても、その PDF ファイルには欧文基本14書体は埋め込まれていない。したがって、Win/Mac マシンに英文のフォントがそれなりに入っていないと、Distiller による PDF/X-1 への変換でこける可能性がある(Helvetica みたいな Win マシンには標準で入っていない欧文書体は特に注意が必要な気がする)。
数式も注意。cmやamstexなどのTeXにしかないフォントを dvipdfmx がどう扱っているのか知らない。PDF に埋め込まれていたり、ビットマップに変換したりしているのでない限り、要注意かも。自分の環境では、Win マシンにもごっそり TeX の数式フォントを入れていることもあって(Illustrator とかで使いたいし)、それがなかった場合にどうなるかは検証していない。

2006/03/05

* なんで確率は 0 以上 1 以下 なのさ
http://yowaken.dip.jp/tdiary/20060305.html#p02

という疑問に呼応した次の話が面白い。

* 確率分布間の「距離」
http://wiki.fdiary.net/lacs/?Pr.App

たしかに、確率0.1と0.2の違いは、感覚的に0.4と0.5の違いとは違う。それをこんなふうに定式化して説明してもらえると、思わず「ぎゅう」ってなっちゃう。

ところで、この話は「確率が 0 以上」であるひとつの解釈にはなるけれど、「確率は 1 以下」の解釈にもなっているのだろうか(読みとれないのは自分の力量不足……)。実は、ょゎさんの疑問を見たとき「測度なんだから 0 以上じゃないと上手くねぇ」と脊髄反射してしまいそうになって、「でも測度なら [0, ∞] でも(のほうが)いいんじゃね?」と自問自答。それだと気持ち悪いくらいしか反論がない。

もしかして、ょゎさんの気持ちは [0, 1)∪{∞} か?
# じょうだんですって
こういう働きをするフィルタがほしい。
((a 1) (b 2) (a 3) (c 1) (d 0) (a 4) (c 5) (b 6))

((a 8) (b 8) (c 6) (d 0))

ようするに、同じタグを持つ要素をまとめ(この場合は加算)させたい。その心は、タグ=>多項式の各項の変数、要素=>多項式の各項の係数とみなして、リスト全体で多項式を定義すれば、こういうフィルタを使って多変数多項式の代数演算システムが構築できるはず。つまり、SICPのex.2.92が解けるはず。
(define (M-filter equ? proc ls)
(let ((L (merge-if-equ-with-car equ? proc ls)))
(if (null? (cdr L))
(merge-if-equ-with-car equ? proc L)
(cons (car L)
(M-filter equ? proc (cdr L))))))

(define (merge-if-equ-with-car equ? proc ls)
(letrec
((head (car ls))
(foot
(let M ((a (car ls))
(rest (cdr ls)))
(cond ((null? rest)
'())
((equ? a (car rest))
(let ((a (proc a (car rest))))
(set! head a)
(M a (cdr rest))))
(else
(cons (car rest)
(M a (cdr rest))))))))
(cons head foot)))
うまくないなあ。つーか、このex.2.92の時点で set! を使うのは、問題の回答としていけないような気もする。でも、"The Seasoned Schemer" の 16th Commmandment(set!はletで束縛している名前にだけは使ってもいい)は破ってないので、よしとすることにしよう。ちっとも先に進まないし。
(M-filter (lambda (a b) (equal? (car a) (car b)))
(lambda (a b) (list (car a) (+ (cadr a) (cadr b))))
'((x 1) (xy 2) (x 3) (y 4) (z 5) (y 6) (xy 5)))

=>((x 4) (xy 7) (y 10) (z 5))

このリストをもってして 4x + 7xy + 10y + 5z を定義するということ。多項式どうしの加算は append して M-filter、積は car 同士および cadr 同士かけたものを combination して M-filter すればいいっしょ。あとは、x^2*y と y*x^2 とかがちゃんと #t になるように変数と equ? を定義して、それらをまとめて代数演算パッケージと連係するようにパッケージ化するだけ。


やあ、ようやく佐川急便が来たよ。これで会社にいける。
佐川のWebにある「お荷物問い合わせ24時間サービス」では、今ごろ大阪から札幌に転送されていることになっている荷物なんだけど、なんとか無事に届いたね。

2006/03/03

こんなことをしている場合ではないという瞬間がたくさんある。時間をへたくそに浪費しているとき、不本意な問題で労役を強いられているとき、自分は思っているほどにさえ何もできないと感じたとき、突き進んでいる人を見るとき、それから、毎日の16:00。
べつやくれいと小島麻由美の親近性について
  • かわいらしい(重要)
  • シュール
  • 異次元(超重要)


上の2つだけだと、ただの奈良美智どまり

2006/03/01

ただの備忘録。

debian では、crontab ではなく、cron.*(cron.daily/, cron.hourly/, cron.monthly/, cron.weekly/)以下に定期的に実行したいコマンドをおいておく。ただし、コマンドの名前にドット(.)が含まれているものは実行されない。これで何日分のログが反映されていなかったことか……

2006/02/28

ひきつづき職場のPCの入れ替え。

弊社では、クライアントマシンのIPアドレスはDHCPで割り当てられている。この更新の頻度がけっこう高く、今日はちょっと固定的に同じ番号を使用したかったものだから、適当に空いてそうな番号を設定してみるという暴挙を犯してしまった。Windowsでは、固定的に割り当てようとしたIPアドレスがネットワークで既に使用されていると、強引に設定はされるものの警告が出る。おそらく、設定しようとしているIPアドレスを求めるARP要求をブロードキャストして応答を確かめているんだろうけど、とにかく警告が出ないアドレスは空いてるってことでしょ? ←これが思い込みであることがすぐに判明する

何がおこったかというと、最終的に警告なく設定できたIPアドレスが、Linux か何かが動いているマシンの固定IPアドレスと見事にバッティングして、相手をハングさせてしまった(おそらくNICが停止してリモートアクセスできなくなった)。管理者の S さん、ごめんなさい。本当にごめんなさい。

今回、相手のマシンは NIC の停止にいたったぽいけれど、ネットワーク上に同じ IP アドレスのマシンが存在してしまった場合(i.e. 自分のIPと同じ送信元IPを持つARPパケットを受信した場合)の挙動は、実装に依存して多種多用らしい。なかには気にせず通信を続ける実装もあるらしく、そんな場合は一部のパケットが別のマシンに取られてしまうことになる。ある種の実装で重複する IP アドレスを検出した場合に NIC を停止するのは、そのようなセキュリティ上のリスクを避けるためなのかもしれない。でも、ルータのような装置が NIC 停止型の実装だったら、かえって容易にサービス停止攻撃をまねきかねないよな。

こういう知識については、あまり知る機会がなかったりする。そんな話題にもしっかり触れている『基礎からわかるTCP/IP ネットワーク実験プログラミング第2版』は 2400 円。ぜひ ;)

『基礎からわかるTCP/IP ネットワーク実験プログラミング第2版』
http://ssl.ohmsha.co.jp/cgi-bin/menu.cgi?ISBN=4-274-06584-7
会社のPCのリース替え。自分のだけなら楽なんだけど。

Windows XP なので、なにはなくても Cygwin をいれなければならない。Cygwin のターミナルはぶっちゃけWindowsのコマンドプロンプトでいらいらするので、Cygterm を入れてターミナルを変えなければならない。ところが、Cygwin をフルインストールしたせいか、Cygterm のコンパイル中に、gccで「_WinMainCRTStartup が multiple definition」とかいうエラーが出てとまってしまう。
とりあえず、Makefile に gcc に与えるオプションとして「-Xlinker --allow-multiple-definition」を追加すればコンパイルできることはわかったものの、これでよかったのだろうか? これはつまり、せっかく新しい PC なのでできるだけ全てのインストールをクリーンに行いたいという病気です。

2006/02/22

Amazonで先行予約開始になったもよう。書店でも、はやいところは25日には並びます。

Amazon.co.jp『RailsによるアジャイルWebアプリケーション開発』
http://www.amazon.co.jp/exec/obidos/ASIN/4274066401/

前田さんのサポートページ
http://awdwr.shugo.net/

出版社のページ
http://ssl.ohmsha.co.jp/cgi-bin/menu.cgi?ISBN=4-274-06640-1

Amazonの先行予約は、Amazonの担当者の裁量で選ばれるもの以外は、出版社がペイを支払うことで実現するらしい。本書がどちらのケースなのか、残念ながら担当者レベルでは真相を知る由もないけれど、ずいぶんいろいろな人をお待たせしてしまった本だと思うので、少しでも早く予約可能になってくれてとてもうれしい。

ところで、巻末にある監訳者の前田さんの略歴には唐突に Scheme という文字が出てくる。あくまでも僕の主観では、これは「とても光栄な皮肉」だ。それはたぶん、この本の制作方法に関係している(あとで全体のフローをきちんとまとめること)。少しでも発行を早めるには、ほかに手段がなかったと信じているのですが、関係したみなさんには多大なるご迷惑をおかけしました。

2006/02/21

何かを観察したいっていうのは、人間の根源的な欲求のひとつだ。観察することにより周囲の危険や将来の出来事を想定したいとか、観察には科学の萌芽があるとか、そういう小理屈はぶっちゃけどうでもいい。ただ単純に、それをもっと見つづけたいという素朴な欲求があると思う。なんていうか、好奇心という概念だけではすませられない、観察という欲望。

たとえば交通事故の現場に遭遇したら、どうしたって見てしまう。不謹慎でも興味本位でもなく、ただ「何がどうなっているのか」を観察せずにはいられない。それだけ。事故や事件の現場はあえて避けて通るという人でも、映画のロケなんかやってたら、(別に興味なくても)とりあえず何を撮っているのか気になって、ちら見程度はすると思う。あと、おとこのこだったら、スーパーカーとか、通りの向こうを走り去っただけで凝視しない? それはもう、興味があるからとか、好きだからとか、カッコいいからとかじゃなく、とにかく見たい。もっとよく見たい。

女の子のスカートが短いのとかも、そのような事例に含まれると思う。いちいちセクシャルな感情を強く抱く男性もいるとは思うけど、そんなのは基地外であって、もっと単純に、ただ状態を観察したいというのが、個人的には本音だったりする。ほとんど交通事故とかと同じ。いちいち性的感情を抱くほど頭のなかはヒマじゃない。異性の下着=性的感情という短絡なイメージは放棄してもらいたい。小学生じゃないんだから。

というはなしを会社でしていたら、おまえは逮捕されてしまえと嘲笑された。だれに嘲笑されたとは、あえていわない。

2006/02/19

『亡命ロシア料理』のローストビーフがうまそうでたまらない。やつらは壺の中にタマネギのみじん切りを敷き詰め、そこに牛肉のブロックを置き、白ワインだけ加えてオーブンにかけるらしい。塩も加えない。タマネギと牛肉のエキスだけをスープにして、あとは壺に任せる。これで極上のローストビーフができるんだって。

このレシピは、化学的にも正しいと思う。NaClのような、分子が小さいわりに味覚を左右する調味料を最初から使ってしまうと、肉汁がしみ込む余地がタマネギの細胞になくなるし、タマネギの甘みがしみ込む余地も牛肉の細胞からなくなってしまう。アミノ酸の分子は塩に比べると巨大だから。

ただ、どうにも我が家には壺が見あたらないので、この知見を応用してスープを作ってみることにした。無水鍋(商標はピタクラフト?)でオリーブ油を加熱し、大量のタマネギのみじん切りを胡椒で軽く炒め、その上に豚コマを設置し、白ワインを半カップほど注いで弱火にかける。5分くらいで十分に水分が出てくる。さらに白菜を投入して、白菜がイメージどおりにしなしなしてきたら、ひたひた程度に水を加える。最後に塩とかサドンデスソースで味付けするだけ。これはうまい。

ここまでは数週間前の話。

今日は、このスープで得た知見を、さらにカレーに応用してみた。カレーを作るとなると下ごしらえに2~3時間くらいかかっちゃうわけで、2~3時間というのは、仮にそれくらいの物理的な時間ができても、実際に不慣れな行動を起こすのはおっくうだったりする。そこで亡命ロシア流タマネギの下ごしらえですよ。

まずはスターターオイルを作る。いずれもホールのクローブ、クミン、カルダモン、黒白胡椒を砕いて、火にかけた油に投入する。焦がさないように注意。油に香りが移ったと信じたら、タマネギのみじん切りと生姜を炒め始める。今回は亡命ロシア流なので、タマネギから出る水気をとばさずに、白ワインだけ加えてタマネギ自身の水分で煮込んでいく。そのため保温鍋(商標はシャトルシェフ)を使う。全体に火が通ったら、頃合いを見てマンゴチャツネやヨーグルトも投入する。チャツネとか、いままでは最終工程に近いとこで入れてたんだけど、分子の大きさを考慮すればこのタイミングだよな。あとは保温鍋にまかせて1時間くらい本でも読んでれば、下ごしらえは終了。

タマネギの下ごしらえができたら、別に茹でておいた豚バラ肉をスープごと加えて、具を煮込む。今日はジャガイモとにんじんとトマト。具材の煮込みも保温鍋に任せる(壺はもってないし)。やっぱり1時間くらいしたら、コリアンダー、ターメリック、ガラムマサラを加え(今日の比率は2:1:3)、最後に塩で味を整えて完成。

curry

従来よりも味のまとまりがいいような気がする。そういえば、にんにく忘れてた。

2006/02/14

先日、『ホテル・ルワンダ』を見に行った。日本公開のためのWeb署名をしたような記憶もあったので。

この映画はとてもいい作品なので、見に行ける人は見に行ってください。
ぶっちゃけ、いまこの映画を見に行っている人は、80%はルワンダやコンゴで何があったか(ニュースとして)知っている人だと思うし、そのうちのさらに80%は、この映画で語られている時間のに何があったかも(ニュースとして)知っていると思う(フツでもツチでもない、コンゴのカビラ政権のことね)。でも、そういう人たちが見に行っているだけでは、いつまでたっても政治臭い作品だとみなされてしまう。まあ、旧社会党系と共産党系の皆さんにもぜひ見てもらって、生ぬるい頭をかちわってきてもらいたい部分もあるけど、この映画は、ただの政治ツールにしてはいけない。だから、やっぱり自衛隊反対とかいってる人は見に行かなくていいです。かといって右翼も見に行かなくていいです。普通の人に見に行ってほしい。すべからく社会人は、ポールのかっこよさを見て、ああ、ぼくは明日も同じような仕事の繰り返しかもだけど、プロとして、会社とか目の前の客とか中途半端な職業倫理なんかじゃなく、ほんとうの品格をむねに自分の仕事に向き合わなくちゃだめだなあと痛感してほしい。実践するのはむずかしくても。

自分の今の仕事が、自分が何かをつっぱってまで品格を保ちたいと思えるものかどうかは大部分の人にとっては問題で、そのジレンマが、高々「お金をもらっている以上……」とか、「人に出して恥ずかしくない……」とか、そういう職業倫理に落ち着いちゃうんだよなあと、自省を含めて感じる。

レイトショー中心だったりするから、かえって大人は見に行きやすいと思う。

2006/02/11

そういえばきのう T さんに、「ブログにプログラムとか書いてるのは正直どうかと思う」と言い放たれたのを思い出した。かわいらしいくせに言うことはこにくたらしい。
小学校の教員的には順序を付けるのは NG なんだろうけど、数学、とくに集合論では、ある関係によって順序を定義し、集合の要素を整列させたい。ある順序集合が整列できるかどうかは、少なくとも「なんとか伝票のどこに印鑑を押すか」よりは重要な問題なのである。だから邪魔しないでください。

あるリストを集合だと思って、その要素 a と b の関係「a > b」を、「a が b よりもリストの左側にあること」だと考えることにする。そのリストの部分集合(必ずしも降順に並んでいない)を、重複する要素を除外して降順に並べるには、どうやるのが効率的か。つまり、
(a b c d e f g h i j)
というリストがあって、その部分集合、たとえば
(f c a c)
を、もとの親玉のリストと同じ順番
(a c f)
にしたいというはなし。

たぶん、これは、ソートの問題の一般化なんだと思う。順序を定義しているリストをランダムアクセス可能なデータ構造に対応させて、関係「>」を自然数における「>」と同一視してクイックソートかなんかしちゃうのがひとつの解法なのかもしれない。つーか、Cとかで配列を使うなら、自然にそういう方法を選択していることになる。

リストのまま整列させるにはどうするんだろうなあと一時間考えて、ようやくたどり着いた貧相な解法は、ビンソートっぽい方法。
(define (be-same-order ls1 ls2)
(if (or (null? ls1) (null? ls2))
'()
(let C ((ls ls1)
(passed '()))
(cond ((null? ls)
(be-same-order ls1 (cdr ls2)))
((equal? (car ls) (car ls2))
(cons (car ls)
(be-same-order (append passed (cdr ls)) (cdr ls2))))
(else
(C (cdr ls) (cons (car ls) passed)))))))

なんでこんなことを考えているかというと、SICP の ex. 2.84 のせい。2種類の型のどっちがどっちを包含してるか判定する方法を示せっていうんだけど(たとえば有理数と実数はどっちがどっちに含まれるか?)、意味を分離させて機械的に判定するには、あらかじめ数値型のタワー構造を表すリスト (complex real rational integer) を用意しておいて、上の be-same-order みたいなので (type-of x) と (type-of y) を整列させてから car をとればいいじゃん。いいじゃん、とか安直に思って、肝心の be-same-order みたいなのがすぐに用意できない、このどうしようもなさ。

2006/02/05

僕みたいな環境で Scheme を使うのは、子どもがクローゼットにしまってあるショットガンを見つけて弄んでいるのと同じなのかもしれない。
昼過ぎに柏から友人Kがくる。仕事を中断して奥様が作ったドライカレーを3人で食べて、しばらくたあいない(たわいない?)話をしてた。たぶんこれはとても贅沢なことなんだと思う。

2006/02/01

今日の LaTeX おばかちゃん。
  • どうグルーピングしても\kernにマイナスの値を指定できない場合がある。マイナスの値を指定した\kernを定義に使っているコマンドに対して、さらに \kern-1zw とかできないっぽいという挙動が、なんとなく見受けられる
  • \item[]の中に"["と"]"を入れるには、[]の中全部を{}でグルーピングする。エスケープしても無駄

ようするに、定義域がはっきりしなさすぎってことか。
むかし、ねえさんと文通してた KM が、2/14 にいよいよ結婚するらしいよ。という電話をさっきうけた。
正規表現に慣れすぎていて、構文解析とかやったことない。しかし避けても通れそうにないので、「10分で書ける、お手軽パーザー」というサイトを参考に四則演算のパーズに挑戦してみることにした。目標は1時間(つまり昼休み)。

10分で書ける、お手軽パーザー
http://fxp.hp.infoseek.co.jp/arti/parser.html

ところで、このサイトの構文定義っておかしくない? 左から解析することを前提にすると、オペレータの右側は必ず Expr のはず。
Expr = Term { (+|-) Term }
Term = Fact { (*|/) Fact }
Fact = ( Expr ) | number

Expr = Term { (+|-) Expr }
Term = Fact { (*|/) Expr }
Fact = ( Expr ) | number


とにかくやってみる。計算の優先順位を示すカッコのパーズは省略。
;; 10minutes-parser.scm
;; 2006/2/1
;; k16.shikano
;; inspired from http://fxp.hp.infoseek.co.jp/arti/parser.html

; Expr = Term { (+|-) Expr }
; Term = Fact { (*|/) Expr }
; Fact = Expr | number

(define left car)
(define op cadr)
(define right caddr)

(define-syntax or-match
(syntax-rules ()
((_ e0 e1 e2 ...)
(call-with-values
(lambda ()
(let R ((ls e0))
(cond ((null? ls)
(values '() '() '()))
((or (char=? (car ls) e1)
(char=? (car ls) e2)
...)
(values '() (car ls) (cdr ls)))
(else
(call-with-values
(lambda () (R (cdr ls)))
(lambda (l o r) (values (cons (car ls) l) o r)))))))
list))))

(define (expr ls)
(let ((parsed (or-match ls #\+ #\-)))
(let ((l (left parsed))
(r (right parsed))
(o (op parsed)))
(cond ((null? o)
(term l))
((char=? o #\+)
(+ (term l) (expr r)))
((char=? o #\-)
(- (term l) (expr r)))
(else
(error "unrecognize expr"))))))

(define (term ls)
(let ((parsed (or-match ls #\* #\/)))
(let ((l (left parsed))
(r (right parsed))
(o (op parsed)))
(cond ((null? o)
(fact l))
((char=? o #\*)
(* (fact l) (expr r)))
((char=? o #\/)
(/ (fact l) (expr r)))
(else
(error "unrecognize term"))))))

(define (fact ls)
(define (list->integer ls)
(let F ((ls ls) (added 0))
(let ((car-int (digit->integer (car ls))))
(if (null? (cdr ls))
(+ car-int added)
(F (cdr ls) (* (+ car-int added) 10))))))
(if (not (char-numeric? (car ls)))
(error "unrecognize fact")
(list->integer ls)))

実行結果

gosh> (expr (string->list "1+3*2"))
7


なんとか昼休みで終わらせたので、不都合があるかもしれない。
もちろん、今日の昼休みだけで全部作れたわけはなく、昨晩から or-match の部分は考えていた。この方法を Scheme で書くには、こんなふうに多値を使わざるをえないように思える(この使い方が洗練されているかどうかはおいといて)。それが面倒。

2006/01/30

SICP を Gauche (R5RS な実装全般?) で勉強していると、真偽の扱いで戸惑うことがある。というのも、SICP では '() を偽としてサンプルが記述されている場合があるけど、ディヴィグ本によればこれは R4RS 流らしい。いや、それともこれは、僕の putプロシージャと getプロシージャの定義の仕方がまずかったから?

そしてもうこんな時間……
「ところで」禁止

2006/01/29

このところのエウレカセブンは、クライマックスにむけてキャラクターの描き方に迷っているように思える。50週もあると脚本が行き届かないのかもしれない。

ところで、自宅で仕事のあいまに、マンションギャラリーというものに行ってみた。マンションを購入するつもりはほとんどないんだけど、近所のあれだけの好立地に建設予定となると本気で考えたくもなる。行ってみると意外に面白いもので、現代的なマンションも悪くないような気持ちになってきた。なんてったってラクだよ。こっちがすることといったらオプションを選ぶくらいなもので、それで展望やセキュリティや空調の完備された心地よい住処が手にはいるんだもん。
で、応募した。最終的には19倍の抽選になったらしく、案の定落選した。こんなものでも、やっぱり落選ってしょんぼりするものだった。

2006/01/27

ううん、昨日の regexp-replace-delimiter-all* では後方参照が使えないな。gaucheのregexp.scmを見ると、regexp-replace-all が最後まで \1 などをサブマッチした文字列に置き換えないらしく、それが原因っぽい。例えば #/foo(.*?)bar/ という正規表現オブジェクトは、内部では ("for" 1 "bar") というリストになっていて、それが regexp-replace-rec という regexp-replace-系プロシージャの請負プロシージャで rxmatch-substring により展開される。昨日の状態で置き換える文字列 に \1 などが指定されていても、最初にデリミタで分解されてしまうので、最終的に取り出される文字列は "1" とかになっちゃう。
置換文字列としてはマッチオブジェクトを引数にしたプロシージャが渡せるので、デリミタを施す処理を外でやるようにすれば対処はできるんだけど……

(define delimiter "%%%")
(define (set-delimiter str)
(string-append
delimiter
(string-join (map x->string (string->list str)) delimiter)
delimiter))
(define (erace-delimiter str)
(regexp-replace-all (string->regexp delimiter) str ""))

(define (regexp-replace-delimiter-all* str . args)
(if (eq? (remainder (length args) 2) 1)
(error
"Need even args -- REGEXP-MATCH-REPLACE*"
args)
(if (null? args)
(erace-delimiter str)
(apply regexp-replace-delimiter-all*
(append
(list (regexp-replace-all
(car args)
str
(cadr args)))
(cddr args))))))

(regexp-replace-delimiter-all* "foobarbaz..."
#/foo(.*?)baz/
(lambda (m) (set-delimiter
(string-append
"|"
(rxmatch-substring m 1)
"|"
)))
#/bar/
(lambda (m) (set-delimiter "..."))
)
 
=> "|bar|..."

なんかだんだん意図がわからなくなってきたけど、ようは regexp-replace-all* だとこうなっちゃうのをなんとかしたいということです。

(regexp-replace-all* "foobarbaz..."
#/foo(.*?)baz/
(lambda (m) (string-append
"|"
(rxmatch-substring m 1)
"|"
))
#/bar/
(lambda (m) "...")
)

=> "|...|..."

2006/01/26

なんらかの構文をルールにしたがってマークアップしたいときに、どんなテキストフィルタを使えばいいかという話。ことに、直前のフィルタリングの結果を次のフィルタリングで上書きされないようにする方法の正解はなんだろう。最初にきちんと構文を解析するのが、もっとも間違いがなく、robustであるのは認める。けれども、よほど汎用性のあるフォーマットでないかぎり自分で構文解析までするのは非現実的だと思う。誰かが、ちょうど自分の目的にあったものを書いてくれていれば、積極的に流用したい。けど、その目的のものを探すコストがばかにならないことも多い。
それなら、「アドホックさ」と「再利用性」のあいだのどこかでバランスをとった解決方法を、その場で作り出すしかないんじゃないかと思う。

「直前のフィルタリングの結果を次のフィルタリングで上書きされないようにする方法」に関しては、とりあえずこんな方法しか思いつかないんですが、この程度の再利用性があればいいんじゃない? だめ?
(define (regexp-replace-delimiter-all* str . args)
(define delimiter "%%%")
(define (set-delimiter str)
(string-append
delimiter
(string-join (map x->string (string->list str)) delimiter)
delimiter))
(define (erace-delimiter str)
(regexp-replace-all (string->regexp delimiter) str ""))

(if (eq? (remainder (length args) 2) 1)
(error
"Need even args -- REGEXP-MATCH-REPLACE*"
args)
(if (null? args)
(erace-delimiter str)
(apply regexp-replace-delimiter-all*
(append
(list (regexp-replace-all
(car args)
str
(set-delimiter (cadr args))))
(cddr args))))))


gosh> (regexp-replace-delimiter-all* "abcde" #/a.*?c/ "xx" #/xd/ "zz")
=>"xxde"

2006/01/23

Joel on Software、amazon で8000円とかのユーズド商品が出ちゃってますが、今週中には緊急に重版してる分ができるはずなのでもう少しだけお待ちください。早まって高値で購入してしまう人がいなければいいけれど。

ところで amazon の在庫情報は、US 本社のデータベースと取り次ぎのデータベースと出版者のデータベースとを連携させているらしい。例えば、市川の amazon.co.jp の倉庫に在庫がなくても、出版社や取り次ぎの倉庫に在庫があれば、「通常は3〜4日以内にお届けします」と表示される。で、どうもこの連携がうまくないときがあって、出版社に在庫があっても「在庫切れです」と表示され続けたりすることがある。Joel on Software に関しては、出版社にも現時点では在庫がないんだけど……(今週できますって)

amazon の在庫表示がゼロになることがどんなに全体での売れ行きに影響するかを考えると、もっと特別に対応すべきなのかもしれないけど、個々の書店への販売担当部署の対応にはリソースの限界があるし(そういうことが重視されていない場合は、とくに)、もっと上のほうの人達との認識の差もあるんだろう。企画編集者としても、いったん商品として本が出荷された状態になっちゃうと、「〜らしい」というレベルの情報しか得にくい。なにせ、重版の出来本が自動的に手もとにやってくることさえないんだから。重版が出来たころに出庫伝票を書いて(しかも手書き)自分で倉庫に赴くしかなく、それってなかなか不便なんだよね。

2006/01/21

うちの目の前はずっと廃屋で、夏になると野バラが咲き、秋になると紅葉し、春になると猫がひなたぼっこをしていた。5年前にこの部屋を借りたときの動機のひとつだったと思う。

DSC_0052 DSC_0072

それがいよいよ取り壊されてしまった。

DSC_0138

さて何かできるのか。何ができても、もうあの神社の裏に忘れられていた空間は戻ってこないんだけど。

2006/01/18

ささやかながら株式投資をしている身としては、もう少し身構える必要があるだろうか? でも、なんか投機スジが騒いでいるだけな気がしてしょうがないので、いままでどおりのスタンスをしばらくは維持しよう。実際、自分が所有している銘柄の評価額はさほど落ちてないし。

にしても、これってUSで数年前に起こったエンロンショックの再演でしょ。いったいこの国は、いつになったらUSの失敗から学習するんだろう。どうでもいいけど、当時エンロンと WorldCom がつぶれたことは、自分が転職をしたことの遠因(といっても直接の利害関係もないわけじゃない)になっていると思っている。

2006/01/16

いっけん仕事で使うスクリプトのように見えてただの道楽シリーズ。けっして就業時間中は遊んでません。つーか、ほんとに日中は(時間的精神的な)余裕なさすぎで、あちらこちらに迷惑をかけている。この場を借りてお詫びします。

で、今日の成果は、なんとなく階層化された文章の見出しに連番をふる gauche スクリプト。
numbering.scm

おなじことをするプログラムは、むかしはPerlで書いて、それからRubyでも書いたけど、いずれも上位レベルの見出しの現在値を保持するのに大域変数を使っていた。大域変数を使わないようにするには継続を使うんだろうなあと知ってはいたけれど、"Seasoned Schemer" を読んで、ようやく何をどうやって継続すればいいのかイメージがわいた。ここでは、現在までのレベルの見出し情報を次の行の処理に継続させている。

(define (numbering file)
(with-input-from-file file
(lambda ()
(letrec
((Ns (lambda (ctrs)
(let ((line (read-line)))
(cond
((eof-object? line)
'())
((leveled? line)
(let ((ctr-lv (length ctrs))
(lin-lv (level-of line)))
(cond
((< ctr-lv lin-lv)
(let ((ctrs (deeper ctrs)))
(cons (put-head line ctrs)
(Ns ctrs))))
((> ctr-lv lin-lv)
(let ((ctrs (add1 (chop ctrs lin-lv))))
(cons (put-head line ctrs)
(Ns ctrs))))
((equal? ctr-lv lin-lv)
(let ((ctrs (add1 ctrs)))
(cons (put-head line ctrs)
(Ns ctrs)))))))
(else (cons line
(Ns ctrs))))))))
(Ns '())))))

2006/01/15

むっかー☆
自宅で仕事してたら Windows2000 Server がブルースクリーンだ。集中力きれちゃったよ。

先日感想を書いた『グラン・ヴァカンス』の作中での時間は、丸2日じゃなくて丸1日だった。ところで、読み終えてから数日たって今ごろ気づいたのは、この作品の世界が晩年のシューベルトのように明るい悲劇性を伴っているってことだ。SFちっくな道具だてでテンポよく語られてしまうので、読んだ直後は単に恍惚としてしまう。シューベルトの後期ピアノソナタ、とくに18番とかも同じで、一聴するときれいでやさしげな旋律なんだけど、ひょんな瞬間に絶望がまとわりついているのに気づく。いつもなら明るい陽光に照らされた光景なのに、いったん地面にうつった影に気になってしまうと、もう影のほうばっかり気になってしかたない、みたいな。

2006/01/04

LaTeX には、テキストをワク囲みするためのまともな環境がない。screenみたいな、minipageを使う環境は全部だめな。footnoteが使えないから。そもそも改ページできないし。で、Knooth本を読んだり Web を見たりしていると、やっぱり本当におかしいのは TeX でも LaTeX でもなく、LaTeX 信者なんだと確信してくる。LaTeX ベースのシステムそのものは、しばらく便利に使わせてもらいます。
LaTeX 信者の特徴は、Web で \ を \ を使って表したがることだ。ありゃどういう風習なんだ? コピペでいきないじゃん。しかしそんなこと言おうものなら、TeXの習得には練習あるのみです、とかいわれかねない(これもまた信者の特徴)。練習して熟練するようなもんじゃないとおもうんだが。ツールだぜ。同じツールでもセンスのいいものなら喜んで勉強したいが。
しかたがないので、ページをまたぐことができ、かつfootnoteを安直に付けられる書籍コラム用のlatex環境を、かつて仕事で作った。今度また必要になりそうなので、仕事中に作った部分は改めてスクラッチから作りなおし、public domain で晒しておくことにしようと思う。

column.sty

出力例(まだ)

実体はlongtable環境。どこでも改ページできるわけではなく、段落の切れ目でのみ改ページできる(もちろん手動で改行を入れればそこで改ページできる)。longtableがけっこう強力なので、このコラムの内部にもほとんどの要素をぶちこめると思う。
なお、column.sty とか名前はついているけれど、スタイルファイルとして汎用に使えるわけじゃないです。コンピュータ書に多い、B5変形で使った場合の一例を公開しているものにすぎないと考えてください。とくに、ワクの上下の角丸の罫線の定義は相当きたない。あくまでも、これをパラメータをあちこちいじればほぼ使える環境がカスタマイズできるはず、というレベルのものであって、「コラム」と呼ばれるスタイルに汎用の要素を切り出して整理したりするつもりはないのであしからず。

2006/01/03

2006/01/02

いまさらだが、正月1日と2日で飛浩隆『グラン・ヴァカンス』を読めた。作中の時間も、いちおう正味2日の出来事になっているようなので、これはつまり、ほぼリアルタイムに、夏の区界をめぐる攻防を追体験したことになる。
実は、amazonからこの本が届いてずいぶん経つ。届いたときにページをぱらぱらめくって、けっこう文字が多かったものだから、しばらく放置してしまっていた。昨日、昼からぽちぽち仕事をしてたんだけど、すぐにむくむくと現実逃避したくなってしまい、それで夕方になって本書を手にとったら一気に引き込まれてしまった。だから、作中とのほぼリアルタイムな読書体験に貢献したのは、正月休みのヒマっぷりではない(実際余裕なさすぎ)。この作品には異様なスピード感がある。左翼ちっくな口上とか、無駄に冗長な人物描写とか、ない。それでも主要な登場人物は魅力でいっぱいだし、彼らに死亡フラグが立って舞台から消えるまでの一文一文は読んでいて本当に寂しい(とくにアンヌ)。
で、これは『廃園の天使I』って銘だけど、IIはいつよ。

2005/12/31

今年は喪中ということもあって静かな年末だった。っていうか、ここ数十年、年末年始は初日の出を名目にして九十九里浜で焚火に耽っていたのに、今年は中心人物の一人が結婚して実家に帰ってしまったから静かなんだ。本人は否定すると思うけど。みんな大人になるとなかなか遊んでくれなくなるわけか。

なにはともあれ、遊び相手といったらだ。

DSC_0130

なんで、こんなにいい男にいい相手がいないんだろう。

文字どおり十年ぶりに野球をした。大人はたまにキャッチボールをすべきだと思った。

2005/12/27

体調(≒モチベーション)がようやく戻ってきた。体調(≒モチベーション)がもっとも悪影響するのは、人間のタスクスイッチだろう。少しくらい体調(≒モチベーション)が低下していても、ルーチン仕事はできますよ、でも、次々と要求とリソースが変化するような仕事の能率は極端に落ちる。

ところで、仕事で使っている簡単なテキストフィルタを Gauche で書き直し始めた(もとは、ほとんど Ruby 製)。こっちのほうが、メンテナンスのコスト(主にモチベーションの維持にかかるコスト)が低そうだから。
あと、ポートやモジュールやマクロのような、どちらかというと非SICPちっくな技術に対する練習も織り交ぜてみるのがねらい。マクロって、こんな場面でこんなふうに使うもの?
(define-syntax tag-case
(syntax-rules (else)
((_ e0 (else e2 e3 ...)) (begin e2 e3 ...))
((_ e0 (e1 e2 e3 ...)) (if (equal? e0 e1) (begin e2 e3 ...)))
((_ e0 (e1 e2 e3 ...) c1 c2 ...)
(if (equal? e0 e1) (begin e2 e3 ...) (tag-case e0 c1 c2 ...)))))

(define (tagged-line-filter tagged-line)
(let ((tag (car tagged-line))
(str (cadr tagged-line)))
(tag-case tag
('column (column-filter str))
('verbatim (verbatim-filter str))
('table (table-filter str))
('numbered (numbered-filter str))
('itemized (itemized-filter str))
('enumerate (enumerate-filter str))
(else (default-filter str)))))

ディヴィグ本だけだと、実用する、という側面がぴんとこない。やっぱり On Lisp か。はやく本にならないかなあ。


時間ないなあ。

2005/12/22

ひさしぶりにトプカでたくさん飲み食いした。たぶん今年最後の夜トプカだろう。一年間お世話になりました。そして、なおさんのプロ意識には学ぶところが多すぎ。

2005/12/21

いまさらだけど、統計ブームだよなあ。

ところで数学には2種類あって、役に立ちやすいのと、そうじゃないの(全然役に立たないやつは、ない)。統計は、限られたデータから全体の傾向について言及するときにウソをつかないようにする方法なので、バリバリの前者である。某新聞の一面がウソをつきやすいのは、統計ではなく経験や思想でモノを言いたがるからだ。ウソをつかれて、すました顔をされるのは心外なので、統計的な常識が世間の常識になってほしい。正確に言うと、統計的な常識には数学的な裏づけがあるものだということが常識になってほしい。
でも、経験や思想で(だけで)モノを言いたがる人には、「数学的」であるということの肝は伝わらないんだよなあ。数字で世の中を説明できるなんて思い上がってんじゃねえ若造が、とでも言いたげな顔で嘲笑される。数学では数字はあつかわないんだけど、説明するのもめんどくさい。ディスコミュニケーション。
とはいえ、統計の教科書だけを読んでると、確かに数字(と数式)だけで世の中を説明しているような印象をうけがち。実際、実験とか調査でデータを集めて魔法の手順や数式に当てはめれば、はいできあがり、というスタイルの統計の入門書も少なくないと思う。どういう場合にどういう手順や数式が使えるか、という情報も、ノウハウとして必要ではあるけれど、それはあくまでも「すでに数学的な正しさを正しいと納得できる人」向けの情報だよ。そうでない人、例えば、「最初の状態と状態を更新するルールが決まってれば、永遠の向こうで状態がどうなっているか断言できる」という話を納得できない人は、たくさんいる。「天気予報なんていい加減のきわみだ」と根拠なく主張する人がいっぱいいる。ところが、今日の天気が晴れであり、この惑星で晴れの日の翌日が晴れの確率はきっかり90%、雨の日の翌日が雨の確率はきっかり50%であるとわかっているなら、明日の天気が晴れの確率はだいたい86%だと断言できるし、それは数学的に正しい。
この天気予報の例は、Wikipediaの Examples of markov chain から取ってきた(計算めんどくさかったんで)。これを信じて晴れの日の翌日に雨が降ったら、最初に仮定した90%と50%という確率については疑ってもいい。しかし、86%が導き出されるプロセスには疑うところがない。この、疑うところがない、というのがポイントで、疑うところと疑わないところを見分けるために数学を学ぶべきだといっても過言ではないと思う。つまり、本当に学ぶべきは、統計で用いられる手順や数式ではなく、そこへいたる数学的な抽象化のプロセスだと思うわけ。
にしては、確率論って統計に比べてさげすまれてない? 統計という、数学的確からしさでデータを判断する考え方に触れる前には、数学的確からしさを納得できるだけの素養が必要で、それには確率を、「事象÷母数」みたいな素朴な認識を越えて理解しておく必要があるんじゃないだろうか。

とはいえ、かくいう自分も、10年前に勉強したことなんてぽろぽろ忘れている。そこで、確率を扱う Scheme のプロシージャでも書いてみようと思い出した。

probability.scm

例えばサイコロを1個ふるという単純すぎるイベントの確率空間は、このように作る。
(define dice6
(make-probability-space
(list 1 2 3 4 5 6)
(lambda (w) (/ 1 6))))

dice6
=>
((1 . 0.16666666666666666) (2 . 0.16666666666666666) (3 . 0.16666666666666666)
(4 . 0.16666666666666666) (5 . 0.16666666666666666) (6 . 0.16666666666666666))

こんな例でも、確率変数という考え方の便利さは感じられる。出た目が偶数かどうかを考えるとしよう。目が偶数かどうかは、ω∊{1,2,3,4,5,6}上のf(ω) = 0 or 1(0: 奇数, 1: 偶数)という確率変数f(ω)として表現できる。これを、Scheme のプロシージャとしてそのまま書くと、こんな感じ(「even-pv」の pv は、probability variable の気持ち)。
(define (even-pv w)
(if (even? w) 1 0))

サイコロをふって偶数の目が出る確率は、直感では 0.5 のはず。これは、この even-pv という確率変数から、実際に以下のように導かれる(一般に確率変数は確率分布関数(離散の場合は確率空間だと思っていい)を導く)。
((lead-distribution even-pv) dice6)

=> ((0 . 0.5) (1 . 0.5))

平均や分散といった統計でおなじみの概念も、確率変数(確率空間)から導かれる。例えば分散はこんな感じ。
(variance dice6)

=> 2.9166666666666665

(variance ((lead-distribution even-pv) dice6))

=> 0.25


メモ
  • まずは離散確率分布
    • 測度とか気にしなくて済む
    • 離散では確率空間≒確率分布だと思っていい
    • 積分より総和のほうがプロシージャを書きやすい
  • 確率変数という考え方がポイント
    • 確率変数から確率分布が導かれる
    • 確率変数から平均や分散が導かれる
    • 確率変数は環をなす

2005/12/17

SICPの2.4項では、複素数を扱うプロシージャをもりもり作る例を説明している。複素数には、直行座標で表現する方法(実部と虚部のペア)と、極座標で表現する方法(ノルムと偏角のペア)があるけど、複素数どうしの和なら直行座標のほうが扱いやすいし、積なら極座標のほうが扱いやすい(積をとるっていうのは回転しながら延び縮みすることだから)。そんなわけで、どっちかの表現だけでなく、両方の表現で扱えるようにしたい。
このように表現の仕方が何通りかあるデータを扱うには、一般にいくつかのやり方がある。一番単純なのは、各データ表現ごとに衝突しないような名前を付けて、かたっぱしからプロシージャを定義していく方法。しかしこの方法では、あるデータがどの表現を意図しているのかをつねに人間が意識していなければならない。そこで、もうちょっと進んだ方法として、データにタグを付けることにする。こうすれば、タグに応じて異なる処理をするようにプロシージャを定義したり、都合がいいような表現に変換してから処理をするようにプロシージャを定義したりできる。
もっと上手いやり方は、2.4.3で説明している Data-Directed Programing という考え方である。これは、データ表現ごとに都合がいいように定義したプロシージャを集めて、それをテーブルとして管理するという方法である。そして、必要なプロシージャは、このテーブルから取ってきて使う。この方法が単純なタグを付ける方法に比べて優れているのは、それぞれの表現ごとにプロシージャの名前を区別しなきゃいけないとか、データの形式を統一しなければいけないといった心配なく、ざくざくとプロシージャを生み出せる点である。そのため、多人数での開発も容易になるし、そもそも不統一な形式で表現されているデータを一括して扱うこともできるようになる。

そうだったのかあ。何人かで並行して開発するとか、データ横断的な処理を定義するっていうのは、こういうことだったのかあ。面白い。面白すぎるよ、SICP。

しかし、2.4.3 だけでは、肝心のテーブルの扱い方はわからないのでした。「Section 3.3.3 でわかるだろう」って、そりゃないよ。3.3.3 まで読み進むのに何週間かかるとおもってんだ。Exercise 2.73 以降が解けないじゃん。

とりあえず "The Little Schemer" の Chapter 10 を参考に、この節でテーブルへのデータやりとりに使われている put と get というプロシージャを模倣するプロシージャを作ってみた。

naive-get-put.scm

とりあえず、とりあえず。

2005/12/14

喜ばしい

* "Joel on Software" の見本ができた
* PHSに待ち受け画面というものを設定してみた

これの3コマ目。

2005/12/11

気が抜けたせいか、今週は6:30くらいまで起きられない日が多かった。そこで思い切っておかいもの。

National 生体リズム 光・めざましシーリング ASSA 洋風シーリングライト LBP58530K::
http://www.amazon.co.jp/exec/obidos/ASIN/B0000C9IYJ/

これで4:00起きの生活がいっそう定着できる。

配送されるのは来週末なんだけど、ようやく我が家の全室(といっても2部屋)に照明が設置されることになる。もう入居して5年になるってのにね。再来週からは、今まで居間兼寝室だけにあった照明を別の部屋に移設し、居間兼寝室の照明として、この目覚しライトを使用することにしようと思う。

ちなみに、上記のリンク先はAmazonだけど、ヨドバシカメラのポイントのみで入手した。だから、一昨日出たボーナスでは、さらに別なものを買えるよ。

2005/12/10

今日の楽しかったこと

* 横浜トリエンナーレ2005

9月に入ってからちっとも余裕がなくて、ずっと行きそびれていた 横浜トリエンナーレ2005 。いよいよ閉幕が近くなったので、天気の良い日を見計らって出かけてきた。なにせ天気が良くないと、エントランスの紅白旗パタパタ(これもダニエル・ビュランの作品)がオモシロさ半分だから。今日は空も青かったし、風もそこそこあったので、かなり好条件だったと思う。

DSC_0110

DSC_0112

ダニエル・ビュラン以外に、特に個人的に楽しめた作品は次の2つ。作品名は忘れた。まあ、作品名はどうでもいいでしょ。
  • 暗闇で青やオレンジ色に光るブランコ
    (ヴォルフガング・ヴィンター & べルトルト・ホルベルト)

  • 実際に乗ることができる。座るところ全体が着色した透明のアクリル(ガラス?)で滑らかに造詣されていて、視覚の上での幻惑的な雰囲気だけでなく、乗って遊んでも心地よい。この写真みたいなブランコが4台、夜の移動サーカスみたいな会場に展示されている感じ。係のお姉さんはいるけど、基本的にどう遊んでも文句は言われない(独占するなど、ほかの人の迷惑になる行為は別)。5分くらい並んだけど、ネズミーランドの666倍は面白いので、2回も遊んでしまいました。押し付けられ管理されるのではない、本当に楽しいインタラクティブな作品だった。


  • 2つの倉庫を結ぶワイヤーを綱渡りする動物たち
    (マーリア・ヴィルッカラ)

  • 基本的には、ここにある写真と同じものだったと思う。気が付かないと、気が付かない。さりげなく完成度が高いのがいい。

ほかにも面白い作品がたくさんあった。できればもう一回くらい、じっくり見に行きたかったかな。ちなみに12月18日まで。

2005/12/09

日替わりハピー

* Tさんと久しぶりにタマリンドにいって、タイカレーを食べたら、予想外にうまかった。昔みたいにご飯がぺちゃぺちゃじゃなかったのが、とくに。
* "Little Schemer" の Chapter 9 が飲み込めた。

で、"Little Schemer" の Chapter 9 は Y-combinator の話題なんだけど、「おまえら名前を付けずに再帰できるか?」という問いからスタートする説明はとても面白かった。で、Web をあちこち見てたら、Y-combinator について「名前を使わずに関数を再帰するための仕組み」だとして説明しているページがあった。そう言っちゃうのは、微妙に誤解だろ……(この本の影響じゃないと信じたい。)

僕自身の古い記憶と(いちおう数学基礎論が専門だった)、いまあちこち調べた部分をまとめると、Church って人が1階の記号論理体系におけるアルゴリズムの決定性を検証するのにλ算法ってのを発明して、それは基本的に変数の名前を置換したり関数を適用するだけで任意のアルゴリズムを定義するような仕組みなんだけど、そこで再帰的なアルゴリズムを定義するための道具として Y-combinator などの「適用しても関数を変化させない」ような関数を作ったって話(勘違いしていたら教えてください)。どうでもいいけど、そんな Y-combinator が話題として盛り上がっちゃうのは、それが Paul Graham の会社の名前であることと関係ないわけがない。

で、僕自身は、それが現実的にどんなアプリケーションで何の役にたつのかは知らない。動くコードとして見たのも、はずかしながら "Little Schemer" が初めて(基礎論の凡人はコンピュータなんて使わないんです!)。それでさらに調べてたら、Y-combinator は memoization に役立つみたいな話を発見。

Y overriding self-application :
http://okmij.org/ftp/Computation/overriding-selfapplication.html

memoization かあ。年内には SICP の Chapter 3 に入りたいなあ。

2005/12/07

数日前に読了した『ケルベロス第五の首』が重版していたらしい。草葉の陰からおめでとうございます。

訳者の柳下さんの日記(11/17に記載)
http://www.ltokyo.com/yanasita/diary/04112.html

日記を見ると、かなり重版修正が入っているもよう。そうなのかあ。いろんな意味で複雑だ(重版で修正って、読者の視点からすると複雑な心境であることを再確認)。それにしても、どこがそんなに変わったんだろう。明らかな翻訳ミスなのか、それとも表現に磨きをかけているのか。複雑な作品だけに、なんとか差分をWebに掲載してもらえるとうれしいんだけど……(それとも、すでに掲載されてる?)

2005/12/06

状況
* hisashim:On Lisp を読んでいるところ
* shikano:ANSI Common Lisp を読んでいるところ
hisashim:mapcan おもしろいよな
shikano:破壊的ですよ
hisashim:いいんだよ、zip のフラットなのができるから

ANSI Common Lispの100ページ(日本語訳のほう)には、mapcanの定義が載っている。
(compose (curry #'apply #'nconc) #'mapcar)

mapcan が破壊的なのは、nconc が破壊的だからだと思うんだけど、だったら nconc を append にすれば、非破壊型の mapcan ができるの?
(define (my-mapcan fn . ls) 
(apply append (apply map fn ls)))

最後のは Scheme だけど、まあ想定どおりに動く。

2005/12/03

さすがに毎日SICPばかりだと飽きるので、ちょっと気分転換に、ずいぶん前に挫折した問題に再挑戦してみる。問題は、8行×9列のマスに、下のようなクエスチョンマーク型の図形を9個描くというもの。
 ## 
#
##
#

#

出展は、すぐ遊べるオンラインパズルというサイトで紹介されていた「九個の?」
http://www.geocities.jp/haayaa2000/puzzle/packing/nine_q.html

クエスチョンマークは90度ずつ回転して使ってもいいし、裏返しにして使ってもいい。つまり、以下の8種類の図形を、互いに重ならないように、8×9のフィールドに9個配置するパターンを探索する。
 ##   ##   #     #   ###         ###
# # # ## # # ## #
## ## # #
# # ## ##
# # # ## # # ## #
# # ## ## ### ###

戦略としては、まず左から右に向かって各行を連結し、フィールドを 0~71 の整数からなる1次元のリストと見なす。そして、0~71 の整数を7つ組み合わせたリストとして、1つのクエスチョンマークを定義する。たとえば、上の8つうち、いちばん左のクエスチョンマークをフィールドの一番左上のマスから描き始めたパターンは、(0 1 10 18 19 27 45) と定義できる。とうぜん、あらゆる 7つの整数の組み合わせがクエスチョンマークを形作れるわけじゃないし、フィールドをはみ出すこともできないから、このフィールド上に描くことが可能なクエスチョンマーク(つまり長さ 7 のリスト)の種類は限られる。そこで、フィールド上でクエスチョンマークとして可能なリストをすべて洗い出し、そこから互いに交わらない 9 つのリストを取り出してくることができれば、問題がとけたことになる。

以前は Python でこの問題に挑戦していて、その時点で前半の「可能なクエスチョンマークをすべて洗い出す」ところまではすんなり解決していた。しかし、そのときは、その集合のなかから互いに交わらない 9 つの組み合わせを得る現実的でスマートな方法がわからなくて、挫してしまっていた。無謀にも、とりあえず9つの組み合わせをすべて求めてからfilterしようとしたりもしたんだけど、せいぜい4つの組み合わせを求めるまでが600Hz/512MのEDENマシンには限界だったようで、それ以上は仮想メモリもすべて枯渇して永遠に計算が進まず……むー(ちなみに、可能なクエスチョンマークは全部で208パターンある)。組み合わせを作り出しつつfilterするようにすれば、時間はかかってもとにかく解くことはできるだろうなあと妄想しつつ、get-combination を定義したりもしてみたんだけど。

いまになって再挑戦する気になったのは、Gaucheに combination-fo-each というプロシージャが用意されていたから。9つのクエスチョンマークの組み合わせを得つつ、それらが互いに交わらないか調べるのには、こんな get-distinct-n プロシージャを用意すればいいはず。
(define (distinct? sets)
(= (length (apply lset-union = sets))
(* (length sets) (length (car sets)))))

(define (get-distinct-n set n)
(combinations-for-each
(lambda (s)
(if (distinct? s)
(begin (display s) (newline))))
set
n))

可能なクエスチョンマークの集合を valid-list とすれば、
(get-distict-n valid-list 9)

あとは、計算が終わるのを気長にまちつつ、ぶログチェックでもしていればいいはず。ガーベジコレクションばんざい!



ただし、まだ計算終わってないので、結果は未確認。

2005/11/30

ひとに仕事をお願いするときに最も難しいことのひとつは、「ダメな成果物をダメと伝えること」である。いまさら感が漂う標語だけど、ちょっと熟慮すれば、一言で片付けられる話でもないことがわかる。だから、たとえば後輩に、「ひとに仕事をお願いするときは、ダメなものをダメって言わなきゃダメだよ」みたいなことだけを言って悦に入っていても、得られる結果は少ない。むしろ、混乱や間違った結果を生みかねないだろう。

まず、「ダメな成果物」の定義があいまい。仕事を頼んだ相手がこちらの依頼に従わなかった場合は、「要求に従っていない」ことをもって「ダメ」を定義できる。ところが現実には、こちらの要求を明白に示せない仕事を依頼することが多い。そもそも、要求を明白に指示できる仕事なら、ひとに頼まない。自分で(コンピュータや機械を使って)やるか、さもなければ、出来合いのモノやサービスを利用すれば用が足りる。それ以外の仕事は、すべて明白に要求を示せない仕事だ。暗殺みたいな仕事のことはよく知らない。でも、「Aさんをやってほしい」とだけ依頼されて、勢いでたまたま傍らにいたBさんもやってしまい、しかも依頼主としてはBさんは別に殺してほしくなかった(深刻に困るわけじゃないけど)……みたいな状況で、依頼主から「オマエの仕事は中途半端だな」といってダメ出しされることは、暗殺者としての職業倫理にはどう響くんだろう? 
この例は、そんなに特殊じゃない。依頼する仕事が、製品やパッケージのデザインとか、コンサルとかリサーチとかシステム設計とかだったら、これと同じような場面がありえる。依頼するドメインに精通していないからコストをかけて外部に依頼するんだけど、精通していないドメインの仕事について明白な要求ができるか? 本当は、依頼される側が、そのことを十分に承知しているべきなのかもしれない。

なんか話が散乱してきたけど、要するに、「ダメな成果物をダメと伝えること」という標語の複雑さの最初の困難は、本来は自分のドメインにない相手の仕事の何をもってダメとみなすかの見極めだといえる。

方法は三つある。一つ目の方法は、相手にダメ出しをする前に、自分が要求を明白に示さなかったことを後ろめたく思うこと。そして、表現できない不満を抱えたまま、相手の仕事を受け入れる。個人的な意見だけど、この方法には震度5以上で倒壊する恐れのあるマンションに入居する可能性があるため、おすすめできない。自分がダメという代わりに、いよいよまずくなってきてから周囲にダメ出しをしてもらう方法ともいえる。実は一番採用されている方法である。
二つ目の方法は、ダメ出しのためにダメ出しをすること。オレがダメだっていってるんだ文句あっか。ありませんので、以降のお付き合いはひかえさせていただきます。
三つ目は、僕にはこれしか思いつかないんだけど、相手に見合った対価を背負った上でダメということ。直接的に金銭を払うことも含むけど、それだけじゃなくて、「ダメ」が相手にとって意味あるようにすること。そうすれば、これはオレにとってダメなだけじゃなく、(オレにとってとは意味合いが違うかもしれないが)オマエにとってもダメであると納得させられるかもしれない。そのためには、相手が相手の仕事で果たしているのと少なくとも同程度の意義を、自分自身の仕事で持たなければならない。それが相手へのダメの説明につながる。ことが多い。相手のドメインにおける相手のスキルを自分が尊重し、自分のドメインにおける自分の立場やスキルを相手に尊重してもらい、相手の考えを尊重し、自分の考えを相手に尊重してもらうこと。「ダメな成果物をダメと伝える」には、実はこれだけの下地がなくてはいけなくて、その覚悟がなければ、黙って相手が一発でイイ仕事をしてくれることに期待するか、そもそも何もせず座っているしかない。

2005/11/27

「ケルベロス第五の首」(ジーン・ウルフ 著, 柳下 毅一郎 翻訳)

帯には、「三つの中篇が複雑に交錯して織り成す謎と真実のタペストリー」って書いてある。これは嘘だと思ったほうがいいと思った。確かに、各部単位で読んでも、ひきずりこまれるような魅力がある。しかし、各部だけを読んだときの面白さが、全体を通して読んだときの面白さの1/3未満であるという理由で、これは長編だ。第三部にあたる「V.R.T」にいたって、それも250ページ目くらいから急激に、第一部と第二部で無造作に放置されていた設定がざくざくはまり出す。第一部と第二部は、それぞれ異なる文体ながら、いずれも丁寧に読むことを強いられる表現で埋め尽くされている。それを読み解いていく作業に伴うストレスが、自然と脳に作品世界のイメージをこびり付かせるんだけど、そうやって第一部と第二部を通じて自分自身がでっちあげたサント・アテナとサント・クレアという惑星系のイメージが、第三部のコラージュ的な記述にきれいに符合したり、あるいは欺かれてたことに気づいたりするのが、快感。その快感を、ひとつの作品としてうまく演出してある。ゆえに、ひとつの長編。
ただし、ほとんどの伏線は、第三部を読んでも、さらにいかようにも解釈できる。たとえば僕は、サント・アテナは地球からの侵略(という表現が適切かどうかはわからない)を二回迎えていると解釈したけど、もしかしたら事実は違うのかもしれない。事実があればね。そういう意味では、デビット・リンチみたいな伏線-回答の関係なのだといっていいと思う(もちろん、ジーン・ウルフのほうが前だけど)。

にしても、やっぱり国書刊行会は期待を裏切らないな。国書刊行会の本を買ったのなんて、何年ぶりだろう(そんな個人的な感傷はおいとけ)。

2005/11/25

昨日はうそを書いていました。
えたいの知れないリストから、どこにあるか分からないアトム(アトムって、実際にはあんまり使わない用語だね)を取り去る deep-rember というプロシージャを勢いで定義してみたんだけど、そんなに簡単な話じゃなかったようです。というわけで、訂正。
(define (deep-rember item list)
(cond ((null? list) '())
((not (pair? (car list)))
(if (equal? item (car list))
(cdr list)
(cons (car list) (deep-rember item (cdr list)))))
(else
(if (equal? item (caar list))
(append (cdar list) (cdr list))
(if (not (pair? (caar list)))
(cons (caar list) (deep-rember item (cons (cdar list) (cdr list))))
(deep-rember item
(append (caar list) (cdar list) (cdr list))))))))
こんなふうな結果が得られる(昨日の定義では、末尾の3が残ってしまう)。
gosh> (deep-rember 3 '(2 (1 4 ((((6))))) (3)))
(2 1 4 6 ())
リスト同士を繋ぐときに append を使っているのは、deep-rember の結果として得られるリストにできるだけ nil を残さないため。nil があると、昨日定義した deep-equal? で、null? を終端条件に使えない。
にしても、もうちょっと整理できないものか。

2005/11/24

samefringe problem

Wilikiの shiroさんのところ でも、2005/11/15 に紹介されている。っていうか、そこで知った。

fringeや継続は使わないとして、与えられたリストをもぐもぐ下へ降りていきつつ、左から同値を検証していくのはどうだろう? つまり、こんな感じ。
(define (deep-equal? list1 list2)
(cond ((and (null? list1) (null? list2)) #t)
((equal? (deep-car list1) (deep-car list2))
(deep-equal? (deep-rember (deep-car list1) list1)
(deep-rember (deep-car list2) list2)))
(else #f)))

deep-car と deep-rember は、勢いで定義すれば、例えば以下のように実現できる。もとのリストたちの構造を破壊しながらたどっていくのはご愛嬌。
(define (deep-car list)
(cond ((null? list) '())
((not (pair? (car list))) (car list))
((null? (car list)) (deep-car (cdr list)))
(else (deep-car (car list)))))

(define (deep-rember item list)
(cond ((null? list) '())
((not (pair? (car list)))
(if (equal? item (car list))
(cdr list)
(cons (car list) (deep-rember item (cdr list)))))
((null? (car list))
(list (car list) (deep-rember item (cdr list))))
(else
(if (equal? (deep-rember item (car list)) (car list))
(append (car list) (deep-rember item (cdr list)))
(append (deep-rember item (car list)) (cdr list))))))

(せめて(car list)くらいはローカルにバインドしようと思った……)

追記(2005/11/25)
間違っていたので、上記の deep-rember は修正。

2005/11/20

SICPの図形言語



ようやくここまでたどり着いた。ひとつの通過点としてコードも晒しちゃう。大きくすると手がつながってないけど気にしない。

この図形言語が取り上げられている2.2.4項は、練習問題そのものは難しくない。たぶん、実際にグラフィックを描く面倒さを乗り越えることと、低レベルから高レベルまできっちり抽象化が分離されていることを味わうところがみそなんだと思った。

グラフィックを描く面倒さは、Gauche の OpenGL ライブラリがなければ乗り越えられなかったはず。着手したときは実際に図形を描かずに妥協するつもりでいたこともあって、segments をリストとして吐き出し、その segments のリストを OpenGL で描画しているだけのお気楽な実装です。したがって、SICP の説明に完全に準じたコードではありません。また、ベースになっている人型の図形(なんで wave なんだろう?)や繰り返しの回数もコードに埋め込んだ状態なので、別のものに取り替えたり、はじっこのへげへげのところをいっそう細かくしたかったりする場合は、コードに直接手を付ける必要があります。教科書の例題なので、むしろソースをコピペしてさくっと実行できるほうがいいと考えました。うそです。OpenGL は何度遊んでみてもかんどころがわからないので、gauche-gl のリファレンスマニュアルで紹介されている例をそのまま使わせていただいたんですが、その描画している部分をうまく分離できなかったというのが本当の理由です。

2005/11/19

昨日と一昨日、Franz社と数理システムが主催のLispセミナーイベントで見聞きしたこと。
ただし、セミナーの要約ではなく、Franz社や数理システムの方と直接歓談する機会があって、そのときに伺った話を含めて自分勝手に都合よく解釈したもの。彼らが直接語った言葉ではないので注意してください。


JavaとRDBMSが有用なのは、やっぱり、金銭管理とか人管理とか在庫管理とか注文管理とかスケジュール管理とか、とにかくそういう「エンタープライズ」と呼ばれる領域だけらしい。現在のソフトウェア産業の中心は、その領域におけるソリューションを提供(提唱?)する行為で成り立っている。すくなくとも、そのように見える。そういうソリューションを提供するビジネスが実体以上に過大視されたのが90年代のITバブルで、それを膨らませていたのがJavaであり、RDBMSだった。すでにバブルの本体はしぼんでいる。じゃあ、マッチポンプだったJavaとRDBMSはどこにいったんだろう? もちろん、どこにもいってない。しぼんだとはいえ、エンタープライズな仕事は、未来永劫にわたって確実に存在する。対象はすでにRDB化されてるし、それを扱う技術への需要が減ることはない。安くはなるだろうけど。もうなってるのか。
エンタープライズな領域でのソフトウェア産業のいくすえは、個人的にはどうでもいい。自分がそこで仕事をしていないからどうでもいい、という投げやりな話ではなく、単にどうでもいい。なぜなら、ここで気にかけておくキーワードがあるとしたら、それは「エンタープライズ」ではなく、「領域」のほうだから。エンタープライズは、ソフトウェアによるソリューションを必要とする問題領域のひとつである。つまり、ほかにも問題領域はたくさんあって、バイオインフォマティクス、法律や特許のような知識情報ベース、自律システムのインテリジェントな制御、その他、僕の知らないたくさんの問題領域で、それぞれに問題がゴマンとある。これらの問題に対しては、かならずしもJavaやRDBMSは使えない。正確にいうと、適しているとは限らない。もっと正確にいうと、適していない。
関係を正規化してちょいといじれば解が出てくるような問題でなければ、RDBMSは有効ではない。複雑な構造のデータはツリーで表せることが多いので、たいていはXMLになるだろう。Javaなら、XMLでもライブラリがいっぱいあって便利だね。けど、たくさんの問題領域ごとにツリーは異なるし、既存のライブラリで単刀直入に扱えるようなツリーじゃない場合はどうすればいい? そもそも、その領域で問題を解決する適当なツリーが見当もつかないような場合は? 見知の複雑なデータ構造を暗中模索しながら効率よく開発するようなマネができるのか?
そこでLispですよ。これほどツリーを扱いやすい言語はないし、どんなに複雑な構造のツリーでも言語そのもので容易に扱うことができる。そのデータ構造を扱う処理を含め、どうせみんなS式なので、カットアンドトライで見知の構造に挑むのも辛い仕事じゃない。そして方針さえきまってしまえば、あとはマクロにするなりコンパイルするなりして、さらに開発効率を上げたり、実行速度を突き詰めたりすることができる。さらにLispでは、Prologのような関係プログラミングのテクニックを採り入れることもできる。これは、複雑な関係を内包したデータ構造を扱うのにうれしい(ちなみに、先日発行された "Reasoned Schema" は、一冊まるごと関係プログラミングの話題)。Allegro Common Lispなら、Allegro Prologとして、すでに関係プログラミングの仕組みが用意されてさえいる(セミナーでは感動もののデモを見ることもできた)。
Lispと同じことをJava(やその他の言語)ではできない。できるにしても、超人的な何か(スキルとか忍耐とか偏狭とか)が必要になる。一方、その他の言語にできることはLispにもできる。サポートとかドキュメントとかライブラリの量とか、そういう社会的なメリット/デメリットについても、少なくともACLなら数理システムの技術サポートが得られるし、提供されている機能も多い。また、Lispのドキュメントやライブラリは決して少なくない。解説書も、これからがんばります。とにかく、他の言語にあってLispにないと積極的に言えるメリットはない。この非対象性が、あえてLispを使う理由だと思う。つまり、もはや「なぜ Lisp を使うのか」ではなく、「なぜ Lisp を使わないのか」ってくらい。
最後にもうひとつ、Lispには重要なメリットがある。それは、世界的な標準仕様があること。RubyやPythonのようなスクリプト言語がビジネスとして成功しない最大の理由は、実はこれなのかもしれない。

2005/11/16

結局僕がHDDの換装ですか、そうですか。ようやく終わりましたよ。

  1. 新HDDをプライマリ、旧HDDをセカンダリに接続して、knoppixを起動。新HDDが/dev/hda、旧HDDが/dev/hdbとして認識される
  2. /dev/hda を fdisk して再起動(/dev/hdb と基本的に同じ構成にしとくほうがトラぶりにくいかも)
  3. 各パーティションを、旧HDDと同じファイルシステムでフォーマットする(mkfs.ext2 および mkswap)
  4. パーティションごとに dump/restore する。以下は /dev/hdb1(旧HDDのパーティション)を /dev/hda1(新HDDのパーティション)に dump/restore する例。これをパーティションごとに繰り返す。
    1. rw で新HDDのパーティション /dev/hda1 をマウント
    2. マウントした /dev/hda1 の直下に移動
    3. dump -0f - /dev/hdb1 | restore xf -
    4. umount
  5. ふたたびknoppixで再起動
  6. 新HDDでブートするように設定
    1. install-mbr /dev/hda1
    2. /dev/hda1 を rw でmountして、そこに移動して、chroot して、lilo
  7. knoppix の CD-ROM を抜いて再起動すれば、新HDDで稼働する


install-mbr のことがすっかり頭になくて小一時間悩んだあげく指摘されて解決したことは秘密。

TODO:あとでちゃんとまとめること。

2005/11/14

信じられないモチベーションといったら、ショスタコービッチもそうだ。党から創作活動を制限されていたジダーノフ批判以降の約4年間、ひたすら机の引き出しの肥やしにするために、24のプレリュードとフーガ、弦楽四重奏第4〜5番、バイオリン協奏曲第1番といった超傑作をこっそり作り続けてたんだから。もちろん、その間は収入もほとんどないわけで、ただ自分のためだけの作曲に労力を投入していたことになる。こう書くと、そのへんの道端やWebで「作品」を発表している自称アーティストやブログロガーと変わらなくなっちゃうな。ショスタコービッチの場合は、発表することはもちろん、作っていることさえ禁じられている状況なわけで、「オレを認めて欲しい」という欲求が一切介入しないところで高度な創作活動を続けていたところがすごい。あこがれる。
溢れてくる何かを信じられる人が本当に羨ましい。羨ましいんだけど、個人的に共感を感じてしまうのは、むしろドビュッシーのようなタイプである。こちらは着想を得ても、なかなか作品に仕上げられない。自分のやってることについて悩みまくって、ようやく形が見えてきても、また悩み始めちゃう。家の外で政情が不安定になったりすると、もう落ち着かない。結局、残せる作品の数は多くないけど、それでも圧倒的に傑作ばかりだから、やっぱりすごい。あこがれる。
ようするに、あれか。モチベーションの発現や維持はともかく、とにかく脳と手を動かせと。

2005/11/13

また Hitchhiker's Guide を見ながらワインが一本あく罠。
昨日今日と、ひさしぶりに人間らしい休日を過ごした気がする。

2005/11/12

バルトークは6つの弦楽四重奏を残しているが、第一作を書きはじめたのが作曲を始めて間もない1908年、第六作が死ぬ数年前の1939年だから、ほとんど一生書き続けてたことになる。ところでバルトークが作曲を始めたのは1904年らしい。この1904年ってのは、世界中でものすごいことが起こり続けた年だったのね。もっとも、こういう共時性は確率としてみればさほど意外ではない。生まれた月日が同一の人がいる確率が、数十人程度集めるだけで100%にかなり近くなるのと同じ程度の意外性。そんなことはどうでもいいんだ。
さっき知ったんだけど、実は彼は死ぬ直前に、第七作目の弦楽四重奏を書き始めていた。なんでそんなに弦楽四重奏が書きたかったんだ? あるいは、なんでそんなに涌いてくるんだ? 作曲家が抱くモチベーションなんてそもそも想像できないけど、弦楽四重奏を書きたいというモチベーションはさらに想像できない。だけど、すくなくとも第一作から第六作を聴いていて感じるのは、苦労して作曲している気がまったくしないことだ。イメージが涌き続けて、涌き続けて、涌き続けて困るっていう雰囲気。これがブラームスなんかを聴いてると、頑張ってる感とか使命感みたいなのが滲んでくる場面がしばしばある。ぼくは交響曲を作らなければならないのです、っていう意気込みみたいな。
意気込んでいい仕事ができる人もうらやましいけど、涌いてきて困る意欲でいい仕事ができる人はもっとうらやましい。両者の違いはなんなんだろう。ただの性格の違いなのか、っていうか、性格の違いって何?

2005/11/09

仕事をこなすときのモチベーションには、「部屋のハエを始末したい」と等価なモチベーションと、「ハエのいない部屋に移りたい」と等価なモチベーションの、2種類があるように思う。いずれのモチベーションも、うるさいハエ(五月蝿い蝿)を何とかしたいというメタモチベーションから帰結するものだけど、それぞれのモチベーションに従ったときの帰結は異なる。「部屋のハエを始末したい」の帰結は、よくて職人(ハエをハシでつかむとか)か、せいぜいエアロゾルのラインを見張る労働者だろう。
こういう場面では必ず注釈が必要なので、いちおう断っておくけど、ここでラインの労働者を揶揄するつもりはまったくない。ただ、「ハエのいない部屋に移りたい」とは決定的に異なるモチベーションで従事する労働のひとつに、工場のラインを見張る仕事があると思うだけだ。だから、金曜の定時直前に上司の仕事をくらった秘書を例に採用したっていいし、出荷直前に致命的なバグ報告を受けたプログラマを例に採用したっていいし、印刷所への入稿ぎりぎりで大きな修正を迫られた編集者(!)を例に採用したっていい。でも、そんな切羽詰ったシチュエーションじゃないほうが一般的なわけで、たぶん、工場のライン労働は、そのイメージがつかみやすい仕事のひとつだと思う。

「部屋のハエを始末したい」モチベーションの最大の特徴は、対処すべき対象が目の前に見えていて、それにエネルギーを割けばいいことがはっきりしている点だ。ハエさえ片付ければ、すべてが終わる。さらに、もうひとつ副次的な効能もある。それは、自尊心にやさしいことだ。だって、ハエを追っている(つまり仕事をしている)ことは他人の目からみても明らかだから。そのため、このモチベーションに従って仕事をしていると気分がいい。仕事の結果も、100%気分がいい。だって、もう目の前にハエは飛んでないんだもん。
ところが、しばらくするとまた別のハエが飛んでくる。必ず。そもそも、最初のハエが部屋に入ってこられたのと同じ経路で、ハエはたえまなく侵入してくる。同様に、ラインの現場でも、今日のノルマが終わったら明日の生産分が待っている。ハエを追い払った後で純粋に安穏とできる期間は、業種によっても違うけど、自分の経験では、せいぜいビールを何杯か飲むあいだだ。あるいは、こうやってたわごとを書き連ねているあいだだ。もちろん、現実には仕事がなくなったらそれはそれで困るわけだけど、そのうち永遠にハエを追い続けるというイテレーションに嫌気がさして、いま飛んでいるハエを始末したいというモチベーションだけでは精神を継続できなくなるだろう。っていうか、僕には無理。

「ハエのいない部屋に移りたい」というモチベーションが魅力的に感じられるのは、そのときだろう。実際にはもっと早い段階で自分が部屋を出る可能性も考えるだろうけど、その思いつきが仕事に対するモチベーションになるかは別の問題だ。
どうして別の問題なのか。部屋の外にはもっとたくさんのハエがいることを知っているから? それもあるかもしれないね。しかし、もっと根本的なのは、それがどういう仕事を駆動するかが異なるからだと思う。何が言いたいかっていうと、「ハエを始末したい」というモチベーションにより駆動される仕事が(自分にも他人にも)わかりやすい形をとるのに比べて、「ハエのない部屋に移りたい」というモチベーションにより駆動される仕事は、ずっと複雑な対応を求められるってこと。だいたい、別の部屋にハエがいないのかどうか知らない。ハエよりずっとやっかいなものがいるかもしれない。そもそも別の部屋があるかどうかも知らない。部屋があるにしたって、どうやってそこにいけばいいのかも知らない。どうすれば別の部屋の状況を知ることができるのかさえ知らない。こういう、何から手をつければいいのかさえ分からない問題への対処は、どう考えても相当分かりにくい仕事だ。つまり、このモチベーションが駆動する仕事は、「ハエを始末したい」というモチベーションにより駆動される仕事とは異なる。あえて色のついた表現をつかうなら、よりクリエイティブな仕事って言ってもいいと思う。ハエを始末しないことがクリエイティブなのではない。このモチベーションによって駆動される仕事をしているときでも、部屋のハエは始末しなければならない(でなければ破滅するわけで)。

もしかしたら、この部屋にやってくるハエの数を減らすことも可能かもしれない(これは、侵入してくるハエを選別するという意味だ。この部屋では、ハエが一匹も入ってこない状況は破滅を意味する。破滅してから部屋の外に出ることもできるけど、一般には無謀だね)。自分に関していえば、ハエを選別しつつ、別な部屋の探索を続けるべきだと痛感しているきょうこのごろ。

2005/11/06

久しぶりにチキンカレーを作った。ほかのことをする気力もなかったので、レシピをまとめておいた。ついでに、だいぶ前に作ったグリーンカレーのレシピも整理した。我が家以外の人の舌にあうかどうかはわかりませんが。

チキンカレーで使うタマネギペースト
http://sidebrake.hp.infoseek.co.jp/onion-paste.xml

チキンカレー
http://sidebrake.hp.infoseek.co.jp/chicken-curry.xml

グリーンカレー
http://sidebrake.hp.infoseek.co.jp/green-curry.xml

2005/11/05

ネガドンを見に池袋にいったんだけど、19:00ころに当日券を買って、係のお姉さんに「整理券とかはないの?」って聞いたら、「今日は立見は出ないと思いますよう」みたいなことを言われたので、ノンキに晩ご飯を食べてジュンク堂で本を買って戻ってきたら、30分前には長蛇の列ができて立見になってた。劇場のお姉さん、Webでの前評判とオタクのクチコミ効果を知らなかったとみえる。にしても、この人達のなかで立見は辛すぎる……と思って、当日券を払い戻して帰ってきた。

しゃくなので、家でまた Hitchhiker's Guide を見る。今日一緒に昼飯を食べた A はトリシアに似てる。どうでもいいが。

2005/11/04

昨日(いうまでもなく祝日)の夜、仕事から帰って一息ついて、ご飯食べて21:00過ぎにウイスキー飲んでたら、郵便局の配達の人がamazon.comの箱をもってやってきた。ここ1カ月くらいの間に少なくとも5回は不在通知を置いて帰るというイテレーションを経て、ようやく日中に来ても留守なことを学習されたらしい。(ちなみに、amazon.comの荷物は、どんなに大きくても普通の定形外郵便物として配達されるので、再配達を除いて時間指定はできない。)

こうしてついに The Hitchhiker's Guide to the Galaxy が我が家にやってきた。アメリカ版DVDは特典の少ないバージョンしか出ていないので、イギリス版を買うか、おそらく特典てんこ盛りで発売される日本版を待つか悩んでたんだけど、イギリス版はPALだし、やっぱり待つこともできなかったので、さっさとアメリカ版を購入してしまって日本版が出たら出たでまた買えばいいか、と思うことにした。オトナってすばらしい。

とにかく、これからはイルカミュージカル見放題なわけですよ。ありがたいことにアメリカ版にもイルカミュージカルだけを切り出した特典クリップは付いているし、しかもこれ、画面の下に歌詞が流れるようになってるんだよね。うまく説明できないけど、海外の子供用番組のミュージッククリップによくある、歌に合わせて歌詞の上をキャラクターが飛び跳ねながらなぞっていくやつ。デズニーアニメでやられるとうざい仕掛けだけど、歌詞がシニカルなこともあって、「おまえらよく分かってる」とイルカをほめてあげたくなる。イルカ! そういえば配給はデズニーだったっけか。
ほかの特典としては、映画ではカットされたシーンがいくつか収録されている。よくある特典クリップではあるけど、原作の有名な場面で映画版にはなかったワンシーン("Hitchhiker's Guide"の「地球」の項目のくだり)も含まれているので、そのへんに不満があった人は購入する価値があると思う。ただし、カットされた理由もなんとなくわかるんだけどね。
あと、「もうひとつの映画版カットシーン」といいながら、おふざけで撮影されたと思われる映像も2編入っているけど、これらはジョークがブリティッシュすぎでよくわかんない。ついでに「無限不可能性ドライブ」ボタンも付いているけど、これは2、3回遊んだらあきるね。

2005/10/27

タイピング時のヘンな癖に気が付いた。"1" を入力するつもりで "a"、"2" を入力するつもりで "s" を入力しがち。しかも! "2" と "s" は形が似ていやがるので、画面を見ている場合でも発見が遅れる。で、そのまま評価すると "ERROR: unbound variable: s" とかいわれて焦るわけよ。
qwerty 配列の弊害か。

2005/10/25

商売を見れば、貪欲に広い市場へリソースを投入するのは当たり前。でも、その広い市場で勝つことにメリットを見いだせないとしたら、どうよ。もっと大義あるやり方でもって、今の市場で食っていくだけの道を選びたくない? 本当は大義みたいな漢臭い表現は使いたくないんだが、ここでは「大義」が重要。本当に「食っていくだけ」じゃ、まったくモチベーションにならない(あしからず、これは「食っていく」ことさえ難しい世界の最貧層を非難する表現ではありません。この国で年収400万未満で生きることにだって、言い知れないやりきれなさがある)。つまり何がいいたいかというと、大衆市場には商売上のうまみはあるが、どのみちつらい仕事なら、より洗練された市場の顧客を選びたいってこと。その選択もまた一つの価値であるということ。もちろん、何を洗練されていると見なすかは、オレ判断でお願いいたします。
いや、業務として割り当てられれば何でもするし、何でもしてきたんだけどね。だから、そんなに片意地なことをいっているつもりはなくて、あくまでも個人的な価値をどこにおくかって話。

この12月にかけての仕事は、ひさびさの Real Work

2005/10/21

素数の魅力を説明してほしいといわれた(一部編集)。そんなこといわれてもなあ。「素敵な数」なんだから魅力的にきまってるじゃん。

ヘンなやつは、付き合っていて楽しい。いわゆる「底が見えるやつ」は面白くない。そうはいっても、まるっきりとっつき悪いやつと付き合う気にもならない。ある程度までは自分の常識に即していて、それなのに「そんな一面もあったのかよ……」と呆れさせてくれるのがいい。わけの分からなさがちょうどいいと、魅力を感じる。
たぶん、素数には、そういう「ちょうどいいわけの分からなさ」がある。「10」にはない魅力が、「23」にはある。

ついでにいうと、一番魅力がないのは「42」だ。

2005/10/20

ひさぶりに強烈に楽しい打ち合わせだった。参加いただいた方々、長時間お疲れさまでした。
朝4時に起きるようになったので、エスプレッソメーカーを買ってみた。

Bialetti MOKA EXPRESS
http://www.bialetti.it/it/catalogue/scheda.asp?id_cat=24&pag=1

安い、うまい、簡単。
実際に使ってみるまで知らなかったんだけど、これって紙のフィルターとか一切不要なのね。ポット全体が2つに分かれて、その間に漏斗形のパーツがあるという構造なんだけど、ポットの下半分に水を満たし、漏斗部分に極細挽にした豆を入れたら、あとは火にかけるだけ。5分と待たずにポットの上部にエスプレッソコーヒーがたまる仕組み。
豆は、 やなか珈琲店 で焙煎して挽いてもらった。家の近くにも会社の近くにもあって、前を通るたびに香りにやられていたので、先週末の土曜日、休出したついでに意を決して入ってみた。ブレンドが店内で飲めることがわかった。しかも150円。しかも濃厚。

朝コーヒーを飲むなんていう習慣はなかったけど、やってみるとクセになる。自分で淹れるのがポイントかな。淹れてるときの香りがたまらない。実はこれ、中国茶でも同じで、あれもサービスしている本人が実は一番の役得なのだ。相手へのサービスが本人にとって喜びになるってのは、仕事の本質じゃないだろうかね。

こうやって話にオチを付けたがるのはよくない。

2005/10/19

携帯デバイスの必要性について議論になると、いつも出てくる意見。「ケータイでいいじゃん」
ちがうんだよ。最低でも qwert じゃないとやなんだよ。qwert が人間工学的にどうこうとかの議論はおいとくけど、とにかくあのケータイの文字入力は、どんなに予測入力があっても、表現を制限したり特殊化したりすることをデバイスによって(暗に)強いられている。たぶん。あれで十分だと思っているのは、実情は思わされているだけで、単に他の選択肢がないから十分だと感じるにすぎない。擬素数を疑わずに素数判定をしてるみたいなもんだね。ちょっと違うか(ぜんぜんちがう)。
以前は、ケータイの文字入力でも結局は人間のほうが慣れちゃうからいいんじゃね、と楽観視してたけど、やっぱりダメだということに気づいた。自分が慣れたくないからダメなんじゃなく、表現の多様性のためにダメだ。qwertにも、いや、そもそもテキストデータ化にも表現の多様性を縮退させる傾向があるかもしれないけど、だからってデバイスの制限によって縮退が加速させられていいのか?
表現の多様性と利便性(コミュニケーション可能性)はどこかでバーターする。とにかく多様ならいいってものでもない。その点、書き言葉、つまりテキストデータのみで扱える範囲の表現は、歴史的にもいろいろあって(右翼:法令とか公文書とか←→左翼:俳句とかジョイスとか、そのたもろもろ。宗教の教典もこの軸では左翼だね)、あるいは共同体における教育とか文化の後ろ盾もあって、比較的センスがいいところでバランスできる手段だと思う。まあ、このバランスだって、そういう歴史とか教育とか文化に基づいているからという意味でしかセンス云々を語ることはできないけど、それはそれでしかたないっしょ。だって表現は、歴史とか教育とか文化に基づくコードの塊を抽象化するものなんだもの。

2005/10/17

なんで TeX には両方向の斜め矢印 がないんだ。
\def\neswarrow{\ooalign{{$\nearrow$} \crcr {$\swarrow$}}}
\def\senwarrow{\ooalign{{$\searrow$} \crcr {$\nwarrow$}}}

2005/10/12

根本から勘違いしている可能性があるけど、

|- T ( x=y <-> y=x ) (ただしT はTheorem)
∵ |- T ( x=y -> x=x -> y=y -> y=x )

この理屈が成立するには、p を T における述語として、 |- T ( p3xxy -> y), |- T ( p3yxy -> x ) となるp3 が必要だと思うんだけど、これって自明なの?(少なくとも僕にとってはムズカシイ。) 「式中に1度しか出現しかない元を抽出できる」、さらには「式中である性質を持つ元だけを抽出できる」なんて、直感的には定理になるとは思えないんだけどねえ。
モチベーションの大小は、細かいところで静かに積み重なり、結果として大きな影響をもたらします。それが分かっていたって、結局コントロールできないんだけどさ。

2005/10/03

問題のある部分は日中に会議があることで、そこでのプレゼン(みたいな何か)がむやみに長い。自分が知っていることを話すのではなく、相手が聞きたいことを予測して話すのがプレゼンです。あと、他人の仕事を引き受けすぎという根本的な問題もある。

ところで昨日は交通博物館に行った。これはまさにあれだ、ノスタルジーとメカニカルと金属の融合。

2005/10/01

映画「銀河ヒッチハイクガイド」を観にいった。そもそも映画化を知った瞬間から、B級な出来に仕上っているに違いないと思いつつどうしても期待しちゃっていて、しかも、期待感でいっぱいになった脳が実物に接触すると、たいていがっかりする。そんなわけで、六本木に着いたころには、帰りにどうやって残念感を補填しようかなあとまで考えていた。
なのに、拍子抜けするくらい面白かった。オープニングから泣きそうになる。僕は、このオープニングの10分くらいを観るためだけにでも、もういちど映画館にいくね。DVDも買っちゃうんだから。
関心したのは、必ずしもマニア向けになっていないところ。2時間の興行映画としてシナリオや演出が相当ねられていて、これなら前提知識なしでも楽しめるはずだ。何よりテンポがいい。テンションのメリハリがはっきりしている。だから、笑いながら見ているうちに気が付いたら佳境で、もうじき終わりなのが残念でならない。もっと新しい景色をみせてください! ともあれ、続編へのフリもあったので期待しちゃおう。あと、Zooey Deschanelがむやみにかわいらしいことを付け加えておく。

原作を粗筋だけでも知っている人は絶対に劇場で観とくべきだと思う。むしろ、ふつーの人に見てもらいたいなあ。一般ウケしといたほうが続編の企画も通りやすいだろうから。だいたい、ろくにマスコミで宣伝していない気がするし、都区内で六本木でしか上映してないってどういうことよ。実際、今日も観にきてるのは明らかにソレっぽい人たちばかりで、土曜日のデートのダシにこの映画を選んでるような人たちは見当たらなかった。
Journalという単語が気になりだしたら止まらなくなってしまったので、タイトルを k16's note に変更します。ちなみに、これは報告ではなく、将来のための記録です。
最初にlivejournalを使っていて、さして気にもとめずにlivejournalでのデフォルトのタイトルを引きずってきたけど、どう見てもこれはjournalではない。しいていえば大学ノートに書きためておくような何か。