2008年 4月 (1)。

Last Modified: Fri May 2 00:06:12 JST 2008

人の話を聞いてはいけません。

おしらせ:

May 01 [Thu]


(07:53)
googlえは画像検索でないときに勝手に上位の画像を表示するのやめたほうがいいと思う。 朝からあんなもんを見ちまった。
(23:26)
技術やコンピュータに未来を託す人々は、 「自分の子供に未来を託す教育ママ」に どことなく似ている。 つまり、すでにあきらめた自分の人生に意味を与える存在として、 自分の分身 (と彼らが思っているもの) に賭けるわけだ。 さもなければ、どちらもあんなに痛々しく見えるはずがない。 彼らとしては、それは自分の人生の意義を決定する問題なので、 それはそれは必死である。

絶望したすえにテクノロジーに自分を同化させる人間を、 いままで何人みてきたことか。新山はこの手の“絶望”には縁がないので、 たとえ自分に子供ができたとしても、そいつに「何かを託す」ことはしないつもりだ。 そいつには、パッパラパーな人生を送らせてあげる。 新山自身が送ってきたのと同じくらいに。

ついでに、将来のコンピュータにも自由気ままな人生を送らせてあげるつもり。 ははは

Apr 30 [Wed]


(21:46)
世の中には、新山の書いていることに共感をおぼえる、といってくる人がいる。 少しだけど。

でも実は彼らこそ、新山のことをまったく理解してない人たちなのだ。 なぜなら新山の信念というのは、「人は決して、決して、 お互いにわかりあえない」というものだから。始めから一切の望みは断たれている。 これは論理的な帰結である。あまりにも強い原則なので、 これが否定されることなどありえない。

にもかかわらず、ときに新山は他人に理解されようと努力している (ように見える)。 しかし、これはそもそも絶望した状態から出発しているので、 ここでいう「努力」なぞはしょせんポーズにすぎない、 ウソっぱちだ。それでも、自分でそのことをわかっていながら、なぜかその努力が “やめられない”と感じるときがある。人生とはそんなもんかもしれない。

こういうとき、オレは論理的な理由によって絶望しつつ、 同時に論理を否定している。ようするに、自分は理性的に崩壊している。 ようするに、1 たす 1 は 1729 である。fuんギゃー.>   そのうち疲れてくるので寝る。

(22:01)
あれ、まだこんな時間か。寝るには早いな。

オレは眠るのが好きだ。いつも眠るのを楽しみにしている。 それから死ぬのも好きだ。いつも死ぬのを心待ちにしている。 だが眠るのが好きだといっているにもかかわらず、 オレはいつもなかなか寝つかない。

問題: 左の欄にあるものと、右の欄にあるものを結びつけなさい。

自由
差別必要
祝福

(22:20)
(答え: 三)
(23:13)
最新の自殺手段がファッションのごとくマスコミを賑わすのは日本ぐらいだろう。 来年の流行は何だ?

Apr 27 [Sun]


(09:42)
中国人にとっての愛国心というのは、 阪神ファンにとってのファン心理みたいなもんだと思う。 ほとんどの阪神ファンはべつに人生かけてはいない (まあ、中には道頓堀に飛びこむようなバカもいるが)。 しょせん彼らはファンなので、「阪神をよくするために頑張る」などという 奴がいたら気持ち悪い。同じように中国人も「中国をよくするために頑張る」 などということはしない。サッサと日本なり米国なり海外に逃げて、 そこから中国を応援するのだ。ようするに彼らは日和見主義なわけだが、 それこそがしぶとく生き残るための秘訣というもんだ。 日本人は中国人に (生命力で) 絶対勝てないだろうと新山が思う理由はここにある。
(10:18)
コドモの世界観とオトナの世界観について。 コドモの世界観は、観察が世界の構造に影響を与えるようなかたちで形成される (観察 → 世界観)。ところがオトナの世界観はこれとは逆向きで、 世界観が観察に影響を与え、すべての観察結果はそれに符合するように 修正される (世界観 → 観察)。もうちょっというと、つまり人は成長するに従って、 世界を自分が正しいと思えるような形のものとして作りかえる。 まず世界があって、その中に自分がいるのではない。 世界は、自分を肯定するために存在していると思うようになるのだ。 この逆転はいつから、どのようにして生まれるんだろうか?

ついでにいうと、この「世界観 → 観察」という物の見方は 多くの観察結果の矛盾を生むのだが、ほとんどの人はその矛盾を 無意識のうちに見落とす。積極的に無視するのではなくて、人間の頭が いつのまにか見落とすようにできているのである。たぶん。 これは潜在意識がものすごくカシコイのかもしれないし、 あるいは顕在意識のほうが意図的に頭悪く設計されているのかもしれない。 いずれにせよ、頭が悪いことは人間にとって祝福すべきことであって、 頭が良くなると人間ゼッタイ不幸になる。ちなみにオレはいまんとこ 不幸じゃないので、おそらく頭も良くないぞ。

(12:05)
いやーそれにしても。 いまやっている pdfminer の開発には、何人か協力者がいるのだが (もちろん面識はないし、お互いに現実的な利害関係もない)、 ここには書けない興味ぶかい情報が手に入る。 とはいえ、新山自身はそんなものにまったく興味ないのだが。 別にヤバい情報ではないよ。

なんとなく時間があったので、/LZWDecoder にも対応させた。 これで、巷に出回ってるほとんどの PDF は解析できるだろうと思われる。 あとは公開鍵暗号を使った暗号化とか、 ほとんど使われない /ASCII85Decoder とかだが、 こりゃもういいでしょ。

(23:19)
きょう図書館でみつけた素晴らしい本、 「柳宗民の雑草ノオト」。挿絵がすばらしい。文体もいい。 基本的には、わりと知ってる草が多いが、 笑ったのは「ネジバナ」である。これはうちの母が前から好きな野草のひとつなんだけど、 うちのママンが毎回「ネジバナがあった」というのを聞いて、オレはどーせ母ちゃんが 勝手にそう呼んでるだけなんだろう、だいたいネジれてるから「ネジバナ」なんて、 いかにもうちの母親がつけそうないいかげんな名前だ、と思っていたら、 この花は本当に「ネジバナ」という名前だと書いてある。これにはおどろいた。

てくるで (ところで)、「ペンペン草」ってじつは ナズナ のことだったって知ってた? オレはいま知ったね。

Apr 26 [Sat]


(15:51)
けさはセンタクをすませ、そのあとしばらくして、やけにカラスがうるさいので 外に出てみたらビックリ、いつのまにかカラスの大群が近所の電線に 集結しており、ゴミをあさっている。被害にあったゴミ集積所は複数あって、 どこでも食い散らかされた袋がそこかしこに散らばってるというありさま。
(21:18)
新山はだいたい罪は家のそばのスーパーですませるが、 いつも必ずチェックするのが魚介類のコーナーである。 ホントは、魚屋があるといいんだけど、いちばん近い魚屋でも歩いていくには ちょっと遠いのよね (なぜおネエ言葉)。それで最近気づいたんだけど、 東京ではサメの肉というのが売ってるのな。しかも安い。 100グラム98円ぐらいだ (東京のスーパーでは、これは安いほうである)。 そんで今日はさっそく買ってきてムニェールにしてみたが、 アッサリしていて食べやすい。ただ、めかじきとかに比べると やや生臭いような気がする。
(23:46)
今日はしばらく放ったらかしにしてあった pdfminer を暗号に対応させた。 はっきりいって、これはやりたくなかったのだが、いまどき ほとんどの PDF が (意味もなく) 暗号化されているんだからしょうがない。 だって政府の出してる“官報”とかも暗号化されてるんだぜ。 ちなみに PDF における「暗号化」というのは必ずしも「読めない」ことを意味しない。 「変更禁止」属性をつけるためにも暗号化しなければならないのである、 なぜか。しかも、この暗号化の方式がややこしい。 いくつも定義されているのだが、たとえば revision 3 という方式は次のようになってる (cf. PDF-1.7仕様書 3.5節):
  1. まず、ユーザが入力したパスワード文字列に次のオクテットを加えて 32バイトまでパディングする。この値は固定で、 "28 BF 4E 5E 4E 75 8A 41 64 00 4E 56 FF FA 01 08 2E 2E 00 B6 D0 68 3E 80 2F 0C A9 FE 64 53 69 7A" である。
  2. この値を md5 に渡し、さらに同じ md5 に この文書の暗号化プロパティの O属性の値を加える。
  3. さらに、この文書の ID属性の値を加える。
  4. このハッシュのダイジェストを計算する。
  5. このダイジェストから最初の nバイト (nは暗号鍵の長さ) をとりだし、 新しい md5 ハッシュに加える。これを 50回くり返す。 (なぜか??)
  6. 最後のダイジェスト値の nバイトを暗号鍵とする。

で、ここでいう「ユーザが入力したパスワード」ってなにか? というと、 じつは暗号化されてるPDFを開くときには、ユーザは デフォルトで「空のパスワードを入力した」ことになってるのである。 つまりパスワードを入力していないときは、上の32バイトのパティング文字列が そのままパスワードとして使われることになっている。

この入力されたパスワードが正しいかどうかを判断するには 次のステップが必要:

  1. md5ハッシュを初期化し、まず上の32バイトのパディング文字列を与える。
  2. この文書の ID属性の値をハッシュに加える。
  3. この md5 のダイジェスト値 16バイトを上で計算した暗号鍵で暗号化する。 ちなみに暗号化アルゴリズムは RC4 で、対称ストリーム暗号なので、 暗号化されたデータは元データと同じ長さになる。
  4. 暗号化されたデータの各バイトを、chr(i) と XOR して また暗号化。ちなみに、この作業は 19回くり返す。 このとき i の値を 1 から 19 まで変化させる。(この数字はどっから来たんだ??)
  5. 最後の暗号化の出力をとり、ここに任意の 16バイトを加える。 (???)
  6. この値を、文書の U属性の値と比較して、合ってたら そのパスワードはOKである。なお比較するのは最初の16バイトのみ。 (そりゃそうだ、だって後の 16バイトは任意につけ加えたものなんだから!)

…なんなんだ、これは。RC4 は暗号化アルゴリズムとしては脆弱なので、 鍵の生成をなるべくランダムにしたり、暗号化したあとの最初の数百バイトを 捨てたりすることは必要らしいのだが、それにしてもこの方式をみると なんかアホっぽく感じる。もっとましな方法はなかったのか。

ちなみにパスワードには 2種類あって、これは文書の閲覧、印刷などを 制御する "user"パスワードのほうである。文書の変更を制御する "owner" パスワードの確認はさらに複雑だが、そこは実装する気もないので 書く気なし。

Apr 25 [Fri]


(21:55)
きょうは、ツツジが満開でしたねえ。

Apr 23 [Wed]


(20:40)
いやー、それにしても、ヒラリーおばちゃんとオバ(ま)チャンの戦いはすごい。 まだ続くとは。もう一生やってればいいのに、と思う。 どうでもいいけど (ddi)、きのうのニュースにあったのだが、米国で googleの広告がインチキだとかいって訴えている連中にオレは尋きたい。 「おまえ、最初から気づかなかったのかい?」と。 「1クリック50ドル」とかいう世界を受け入れている時点で、 彼らはすでにマトモな感覚を失ってると思う。しかし、誰もそのことを 疑問に思わないという世界。すてきだ。
(21:36)
オレはまだ本音の 5% も言ってないぞ。

Apr 22 [Tue]


(07:43)
なぜかおそろしい夢をみた。 米国の選挙戦キャンペーンで、どっかの共和党候補者 (マケインではなかった) の 講演を聴いているという夢である。まわりは熱狂的な支持者ばっかりで、 新山は「なんでオレがこんな場違いなところに? 関係ねーじゃん」とか思っている、 という構図だった。いま考えても、本当に場違いだった。 まわりはなんかみんな保守的そうなのが多かったし、新山が 共和党に対して抱いているイメージというのはまさしくああいうものなのだと思う。 それにしても、新山はそもそも米国のことなんか関係ないし、 共和党なぞなおさら関係ない、つまり「ダブル無関係」なのに、 あの夢はいったいなんなんだ。NYTimes の読みすぎか。
(21:05)
くそー、辞書がほしいぜ。辞書辞書。しかしその辞書は (もしそんなものが存在するとすればだが) 言葉で書かれていない。 それが問題なのだる。

Apr 21 [Mon]


(20:48)
いやー、あいかわらずオチャワンで飲むお茶はうめい。 さて、新山はコーディングの速度はそんなに速くない (まあ、人並み程度) と思うが、構想から完成までの時間は なるべく縮めるように心がけている。つうか、「構想」の時間が かなり長い。新山はキホン的に 9時〜6時で超過時間での仕事はしない (つもり) だけど、本当の仕事時間はもっと分散されている。 肝心な構想の部分は、じつは会社ではたいしてやっていなくて、 いちばん構想が「練れる」のは帰りの自転車や風呂に入っているときだ。

不思議なことに、こういうときは特に「考えごとをしている」という 状態ではない。ナーンも考えずに自転車をこいでいるだけである。 (あんまりボーっとしてると、車にぶつかってしまう。) しかし、それでもいいアイデアは勝手にやってくる。 これがどのくらい生産的かというと、だいたい毎日、家に帰るまでに 1コか 2コは「あっ、こうすりゃいいんだ」とか「明日はこれをやってみよう」 という考えを思いつく (新山の頭は夕方にもっとも爆発しているという特徴はずっと変わっていないので、 たいていのアイデアは行きよりも帰りのほうがよくでる)。 これは、自分としてはものすごい生産性だと思っている。 もっとも、出てくるアイデアは別に仕事に関連したものダケではないけどね。

Apr 20 [Sun]


(07:56)
またぴちょんくんの話ですが…。

クラス定義における名前空間のふるまいを調査していて、 またも一貫性のない奇妙な現象に気がついた。 たとえば以下のコードであるよ:

a = 'global'

class B:
  print 1, a
  a = 'B'
  print 2, a
  
class A(B):
  print 3, a
  a = 'A'
  print 4, a

  def __init__(self):
    self.a = 'instance'
    print 7, a, self.a
    
  @classmethod
  def foo(klass):
    print 8, a, klass.a
  
  @staticmethod
  def bar():
    print 9, a

print 5, B.a
print 6, A.a
A()
A.foo()
A.bar()

これを実行すると、以下のような出力が得られる。

1 global
2 B
3 global
4 A
5 B
6 A
7 global instance
8 global A
9 global
ここで気づいた (というか、いままでも知ってはいたけど あんまり意識してなかった) 癖というのは、クラス定義 A の中では クラス変数 A.a がスコープに入るのに、 メソッド A.__init__ の中では A.a は スコープに入ってないということである。つまり class というのは 字句的なスコープを作らないとゆうわけだ。 見た目的にはレキシカルになるべき構造であるのに、である。

注目すべきなのは 1 と 2、および 3 と 4 の出力である。 クラス定義 BA の中は、どちらも クラス変数 a を定義するまではグローバル変数が見えている。 a が定義された行からグローバル変数は消え、 クラス変数が見えるようになる。グローバル変数の 'global' の値は あいかわらず残っているので、これはグローバル変数を書き換えているわけではない。 これは以下のような関数と比べると違いがよくわかる。

a = 'global'
def foo():
  print a  # エラー
  a = 'local'
  print a

この一貫性のなさはなんなんだ。クラス定義における名前空間だけは 他から「浮いている」ように見える。 まあ、Python はもともとオブジェクト指向と関係なく、 クラスにしろインスタンスにしろ、名前空間を使ったその場しのぎの実装だったので、 しょうがないのかもしれないけど、なんか意味があるのかな?

(08:56)
食後のお茶をチャワンで飲むとなぜかうまいことについて。 新山は、食後に淹れる緑茶を、ご飯を食ったあとのお茶碗に入れて飲むのがすきだ。 こうするとなぜかうまく感じる。なぜだろう? ひとつは、茶碗についた コメの風味が微妙に残っている (?) ということがあげられが、 たぶん本当の理由は、淹れたてのお茶を茶碗にそそぐと、その形状のために すぐに適度な温度まで冷めて飲みやすくなる、ということだと思う (はい、新山はネコ舌です)。そういえば「茶碗」というのだから、 もともとはお茶を飲むものだったわけだ? しかし「お茶碗」というと、ごハンを食うためのもので、 お茶を飲むほうは「湯呑み茶碗 (ぢゃわん)」といわれてしまっている。 なんで入れ替わってしまったのか。

てくるで、思うにネコ舌の真の苦しみとは「熱いものが食えない」 ことではない。食うことはできるのである。が、熱いと味がわかんなくなるのだ。

(20:28)
TODO:
そういえば連休中に実家に帰るときは岡埜栄泉の豆大福をオミヤゲに 買っていこう。これを忘れないこと!
(23:38)
まだしつこく続けている Python 型推論について。 あれからいくつかモデルを作り直したが (つまりコードを全面的に書き直すということを何度もやった)、 よーやく「これで行けるだろう」という枠組みができたような気がする。 今日の時点で、クラスや配列をまともに扱えるようになった。 pointer aliasing の問題にも対応した。

ポインタ (のようなもの) を使う言語の型推論でややこしいのは、 参照を追うのがタイヘンだということである。 pointer aliasing というのは、ようするに以下のようなコードである:

def foo(x):
  x[2] = 'a'
  return

a = [1,2,3]
b = a
foo(b)
c = a
print c[2]

問題: この最後の print で表示される値は何でしょう?

似たようなことはクラス属性でも起こる。 しかも Python では変数の中にはなんでも入りうるから、 これが x[2][0] = 1 とか a.b[0].c.d[2] = 2 とかに なったときでもちゃんと動かなければならない。 新山は実際にオレが作ったプログラムでこれを使いたいので、こういった Python の言語仕様を (ライブラリを除いて) すべてサポートしなけりゃ意味がない。 ただしさすがに名前空間だけは固定で、locals()__dict__ に 直接代入したり evalexec は使わないと仮定してるケド。

結局、新山がとったのは 「Python プログラムを、参照透過なグラフに変換してから型推論する」 という方法である。ただし本当に Python コードを参照透過にするのは無理なので、 ここでは実行順序が犠牲にされている。ようするに、コードの各行が 考えられるあらゆる順序でシャッフルされたと仮定して、そのときに個々の変数や 関数のとりうる型の極大集合を計算するのだ。プログラム内で使われる (関数も含む) 型の数はかならず有限なので、これらはいずれ収束し、計算は終了する。 これは [Wilson, 95] でやっていた方法と似ている…ような気がするが、 新山はこの論文のアルゴリズムをちゃんと理解できていない。それに、 あっちは C だからな (まあ、それでも Python は & とか * がないので (あるのは C でいうところの []-> だけ) マシな気がする)。

さて、C よりも大変な部分として、Python は非常に動的なので、 たとえば a.b() というメソッド呼び出しがあったら、 ここには不確定要素が 2つある。まず 変数 a には異なるクラス (のインスタンス) が入る可能性があるし、 属性 a.b に入っている関数 (=メソッド) も つねに不変とは保証できない。実際、新山は状態遷移をモデルする lexer などで、 呼び出すメソッドを aliasing することがよくある。しかしこれも 現在のモデルで表現可能なことがわかった。静的に型が決まっている言語との違いは、 静的な言語では依存関係が最初から (ソースを見れば) 明らかなのに対して、 Python では (その動的さのため) オブジェクトどうしの依存関係の全貌が 最初から明らかになっておらず、グラフを expand する形で動的に計算していかなければ いけないことである。で、運が悪ければこの過程には指数的な組み合わせが起こる。 まあ、実際的にこういう例で使われる型は少ないから爆発しないと思うけど…。

残りやること TODO:

うええええ、まだこんなにある。 ひとつの言語を完全にシュミレートするのは、すんごく大変だということがわかった。

そしてこれらが終わった時点で、list.append()sys という 組み込みのメソッドやモジュールをいくつか実装してようやく実用になる。 まだまだ先は長いが、ここまでくればあとは要するに力仕事だけだ。 「可能か不可能か」という部分にケリがついたので、精神的にはかなり軽くなった。

Apr 19 [Sat]


(13:22)
無色のやつほど色に染まりやすい。 したがって、適度な偏見をもっておくことは重要である。

Document ID: b7a480fe050fe194c549abc05a8ce937

Yusuke Shinyama