さよならピアソン

ピアソン桐原のピアソングループ離脱にともない、 ピアソンの技術書和書は書店在庫限り だそうだ。

聞いたとき、これは日本のソフトウェア開発にとってとんでもないことだと思った。それ以前に私にとっても困ったことだ。だから、在庫限りであるならばそれを押さえなければならないということで急ぎ書店へと向かった。 しかし、見渡しても買うべき本をそれほど見つけられない。これは何故だろう。

なるほど、古典的名著は数多くある。『達人プログラマ』『アナリシスパターン』『リファクタリング』『計算機プログラムの構造と解釈』『Effective C++』『Effective Java』『人月の神話』『テスト駆動開発』『詳解UNIXプログラミング』『プログラミング言語の概念と構造』『モダン オペレーティング システム』『分散システム―原理とパラダイム』『Java仮想マシン仕様』。どれもその技術分野を触る人なら最低限読んでおく必要のある本ばかりだ。そして、『Modern C++ Design』。

Modern C++ Design―ジェネリック・プログラミングおよびデザイン・パターンを利用するための究極のテンプレート活用術 (C++ In‐Depth Series)

Modern C++ Design―ジェネリック・プログラミングおよびデザイン・パターンを利用するための究極のテンプレート活用術 (C++ In‐Depth Series)

これはC++の歴史をかえた本だ。それに個人的にも、この本をたまたまふらりと入った六本木の青山ブックセンターの新刊棚で手に取らなかったら私はソフトウェア開発を職業にしてない。 そうだとも、あの華々しいC++翻訳書の数々を覚えているだろうか。だからこそ私だって、この度のニュースを「とんでもないことだ」と戦慄したのだった。

だが、買うべき本がない。私に関して言えば上のような基本中の基本の本はもう買ってある、というのもあるけど、それだけではない。

  • C++とかCORBAがそこら中で使われてる時代でもないし
  • Effective Javaとか、開発文化じゃなくて純粋技術の話は読みやすいから原書でもいいし
  • SICPとか原書の方が読みやすいとすら言われるし
  • タネンバウム先生の本は分厚いから、まー売れなそうだし、それを仕事で触るのでなければ必須でもないし
  • そして、Javaオブジェクト指向デザインもコンピュータサイエンスも、ピアソンのラインナップの後続にあたる最近の「must have」な本はみんな翔泳社オライリージャパンが翻訳している

これは売れなかろう。技術書から撤退という判断はやむなしなのかもしれぬ。

英語が苦手な人でも読んでほしくて惜しまれるのは

ぐらいか。

『東京市制概要』

東京市制概要 表紙

ふらりと立ち寄った古書店で昭和十年版『東京市制概要』というのを見つけて買ってきた。結構役に立ちそうだ。

アメリカ系の会社で地図をやっていると「なんでTokyo Cityってないの?」みたいな知識がたまに必要になる。なんでかというと戦時体制がどうたらという話になるけど、この辺の知識は全部二次、三次の資料に基づく受け売りだ。実際のところ府市統合以前がどうで、その後どうなってという正確な知識には欠けている。その辺きちんと知りたいよなーと思っていたところにこの本との出会いである。これだから古書店巡りはやめられない。ぼちぼち読んでいこうと思う。

ぐんまRuby会議01で発表した

ぐんまRuby会議01 で発表してきた。

講演依頼では、「Rubyを通じて見てきた世界、ソフトウェア開発者としての世界観を語ってほしい」とのことであった。そうすると、私がRubyに関わっている理由は2つだ。

  • 個人的にRubyが好きで手に馴染んでいて、これからも継続してほしいから
  • 私が望む世界が実現されるための手段としてRubyは有効であり、Rubyに発展してほしいから

上についていえば好きなものを好きなのにそんなに理由はない。たぶん「プログラマのあるサブセットにとって自然で親しみやすく」というMatzの言語デザイン意図にうまくはめられたというだけだろう。 下についていうと、Rubyはあくまでも手段であり話題の主役ではない。が、Matzの意図についてはMatzがすでに多くを語っているし、私は下について話すことにした。内容は 過去の記事 +α。

ある人の世界観を共有する手段としては、背景にある読書歴というのが欠かせない。またそれらの書籍を通じてよりハイコンテキストな情報を限られた時間で伝達できる。だから今回はいろいろな書籍を挙 げながらMad web programmerと私の望む世界とそこに至るための私自身の取り組みについて話した。

スライドだけ見ても意味不明で、むしろ誤解を招きかねない部分もあるのでスライドの公開予定はない。ただ、その中では次のような書籍に言及した

正直なところ、あの内容を話すのも準備するのもかなりしんどい。それで若干準備し切れていない部分もあった。需要があればまたどこかで話したいと思う。

光目覚まし時計

光目覚まし時計というものを初めて買った。騒音でなく光によって目覚めを図るというものだ。2ヶ月ばかり使っている限りではなかなか好印象だ。OKIROという直球な名前も一周回ってセンスよくすら感じる。定価は39,000円だけど、Amazonではもっと安く売ってたし。

私はもともと睡眠時間が長いたちで、日常生活を送っているとなかなかその体質に足るだけの睡眠時間を毎日とることは難しい。 それで起きられなくて目覚まし時計に頼る訳だけれども、生半可なものでは起きられない。新しい目覚まし時計を買うとしばらくは起きられるが、一週間ぐらい経って新しい機体の操作に慣れると半ば眠ったまま無意識に止めてそのまま寝続けてしまう。そういうわけで、爆音目覚ましだとか音色が豊富な(=その音に慣れるのを防ぐ)目覚ましだとかをいろいろと試してそれなりに効果は得たものの完璧とはいかなかった。

それに比べると現在はOKIROによって次のように改善されている。

  • 指定した時刻よりも少し前から徐々に明るくなって日の出を再現する。明るくなったら起きるという自然な仕組みに基づいているので目覚めがすっきりする。どのぐらいの時間をかけて明るくしていくかは調整できる。
  • 従来は、目覚まし時計の音がまだ眠っている他の人に五月蝿くて迷惑だろうと考えて、早めに音を止めてしまっていた。しかし、それが為に二度寝を防げないことがあった。光であれば音波よりも遥かに指向性が強いので自分にしか影響しない。だから安心して、起き上がって着替えて顔を洗うまで目覚まし時計を放置しておける。目覚まし時計を止めた状態で二度寝という最悪のパターンを避けられる。
  • 個人的には音よりも光の方が目覚めやすい模様。これは体質によるだろうけれども、私は慣れればある程度大きな音が鳴っていても寝られる。けれども1時間明るい光を間近で照らされるとさすがに目が覚める。

ちなみにメーカーは読書灯としても使用可能とか時差ぼけの解消に有効とか謳っているけれども、こちらは試していないのでわからない。Amazonでの評を見ると読書灯としては光がどぎつくて目に厳しいとかいう意見もある。 光の照射面積が狭いという意見にはあまり賛同しない。私も寝相は良くないけれども、上下逆さになるとかベッドから落ちて寝ているような寝相でなければ有効範囲内には頭があるだろうと思われる。

SSD/Linuxをvirsh+kvm+qemuにインストールする

OpenMicroServerカーネルビルド環境としてSSD/Linuxを用意しようと思う。 VMWare用のイメージが提供されているので以前はVMWare Fusionでそれを動かしたことがある。 今回は故あってKVM+qemu環境で動かすことになった。

インストール

サポートサイト からVMWare実行イメージをダウンロードする。zipで固められているのでこれを展開する。

% unzip ssdlinux-1.0.0-20121220.zip

このイメージは3つのディスクイメージから成っている。

% ls
hda.vmdk  hdb.vmdk  ssdlinux.vmx  vmboot.fs

hda.vmdkがルートファイルシステム, hdb.vmdkがホームディレクトリらしい。 それでvmboot.fsがext2のrawイメージで起動用FDのイメージだ。

最初hda.vmdkの中にbootセクタを探そうとしたり、hda.vmdkをqcow2に変換したら動かなかったりといろいろ苦労した。幸いなことにqemuがそのままvmdkを読めるので特に変換はせずに使用する。

VMWare用のssdlinux.vmxを参考に、virsh用に次のようなドメインを定義した。 virt-managerの手も借りたので下記は最小セットではない。

<domain type='kvm'>
  <name>v254</name>
  <description>Build Environment for OMS firmware</description>
  <memory>262144</memory>
  <currentMemory>262144</currentMemory>
  <vcpu>1</vcpu>
  <os>
    <type arch='i686' machine='pc-0.12'>hvm</type>
    <boot dev='fd'/>
    <bootmenu enable='yes'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <cpu>
  </cpu>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/bin/kvm</emulator>
    <disk type='file' device='floppy'>
      <driver name='qemu' type='raw'/>
      <source file='/var/lib/libvirt/images/ssdlinux/vmboot.fs'/>
      <target dev='fda' bus='fdc'/>
      <alias name='fdc0-0-0'/>
      <address type='drive' controller='0' bus='0' unit='0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='vmdk'/>
      <source file='/var/lib/libvirt/images/ssdlinux/hda.vmdk'/>
      <target dev='hda' bus='ide'/>
      <alias name='ide0-0-0'/>
      <address type='drive' controller='0' bus='0' unit='0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='vmdk'/>
      <source file='/var/lib/libvirt/images/ssdlinux/hdb.vmdk'/>
      <target dev='hdb' bus='ide'/>
      <alias name='ide0-0-1'/>
      <address type='drive' controller='0' bus='0' unit='1'/>
    </disk>
    <controller type='ide' index='0'>
      <alias name='ide0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
    </controller>
    <controller type='fdc' index='0'>
      <alias name='fdc0'/>
    </controller>
    <interface type='bridge'>
      <mac address='52:54:00:99:cf:fe'/>
      <source bridge='br0'/>
      <target dev='vnet0'/>
      <model type='e1000'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
      <source path='/dev/pts/1'/>
      <target port='0'/>
      <alias name='serial0'/>
    </serial>
    <console type='pty' tty='/dev/pts/1'>
      <source path='/dev/pts/1'/>
      <target type='serial' port='0'/>
      <alias name='serial0'/>
    </console>
    <input type='mouse' bus='ps2'/>
    <graphics type='vnc' port='5900' autoport='yes' listen='127.0.0.1' keymap='en-us'>
      <listen type='address' address='127.0.0.1'/>
    </graphics>
    <video>
      <model type='cirrus' vram='9216' heads='1'/>
      <alias name='video0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
    <memballoon model='virtio'>
      <alias name='balloon0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </memballoon>
  </devices>
 </domain>

このXMLをssdlinux.xmlに保存して、

% virsh define ssdlinux.xml

と定義する。

ここでvirt-managerを起動して、GUIからこのドメインを起動した。

シリアルコンソール

さて、何をするにせよvirt-managerのターミナルエミュレーション経由では不便極まる。 デフォルトでDHCPクライアントとSSHdが立ち上がるので、起動してからの作業ならSSHでも良い。でも できればシリアルコンソールから操作したい。

そこでbootディスクをマウントして修正してやることにする。幸いなことに起動ディスクに入っているのは独自のブートローダーとかではなくGRUBなので、勝手は分かっている。

% mkdir /mnt/floppy
% mount -t ext2 /dev/fd0 /mnt/floppy
% cd /mnt/floppy/boot/grub

で、menu.lstの中身を編集してカーネルオプションとしてconsoleの指定を足してやる。

kernel          (hd0,0)/vmlinuz root=/dev/hda1 clock=pit nosmp noapic nolapic console=tty0 console=ttyS0,9600n8

そうしたらアンマウントして再起動でOKだ。

% cd /
% umount /mnt/floppy
% shutdown -r now

virt-managerのView -> Text Consoles -> Serial1を選択すると仮想シリアルポートに起動中のメッセージが出るのが分かる。

これだけだとシリアルからはログインできないのでgettyも設定してやる。Graphical Console VNCの方に戻してログインしてから、

  • /etc/inittab にttyS0のエントリを足す

    c7:2345:respawn:/sbin/agetty ttyS0 9600

  • /etc/securetty のttyS0の行をuncommentする。
  • kill -HUP 1 する。

これでホスト環境で virsh console v254 とすればログインできるようになった。

指定バイト数ぐらいの長さの文字列を読み込む方法

IO から指定したバイト数以内の長さを読み込みたいが、多バイト文字の途中で切れてしまうのは嬉しくないのでそういうときはもう少し読む、というような処理を書きたいことがよくある。 これ、というメソッドは見当たらないので仕方がないから自前でバッファリングしたりしてなんとかしていたのだけど、 IO#gets にそういう機能があることが分かった。

IO#gets はseparatorに nil を指定するとseparateせずにファイルの最後まで読む。それからもう1つ、読み込むバイト数の上限を指定できる。この上限指定は1.9ではもちろん多バイト文字を壊さないようになっている。だからこれらを組み合わせて io.gets(nil, limit) とすると希望の動作をする。行操作でもないのに gets というのはちょっと思いつかないね。

余談

なぜ突然こんなのに気づいたのかというと、今書いているライブラリの関係で IO の挙動を細かくみているのだ。

IO クラスはもともと結構大きなクラスだったのだが、Ruby 1.9になってM17Nが入ったためにエンコーディングがらみでさらに挙動が複雑になった。もはや StringIO みたいに自前で IO もどきのクラスを書くのは容易ではない。そこで IO もどきを作るのを助ける IOable というライブラリを書いている。

性的保守主義と性同一性障害の親和性

性同一性障害の典型例、つまり 自己の性的同一性を明確に認識——身体との間には齟齬があるにせよ自分の人格の中核を成す性別には疑問がない——し、ヘテロセクシュアルで、性的自己認知と性別役割に葛藤が無く、その現象を「性同一性障害」として医療化することを受け入れている人にとって性的保守主義は甘い誘惑だ。

性的保守主義と抑圧

ここで性的保守主義とは、最も典型的な男、女という性に性現象のすべてを回収するものとしよう。彼らは例えば社会での男女の性別役割を自然で当然のものと考える。そこから外れる人を「男なのに○○」「女なのに○○」と自己の属する多数例を基準に評価する。同性愛は彼らに言わせれば例えば「女と寝るように男と寝る者」(レビ記18:22)だ。私が知人の男性同性愛者を見たり資料を読んだりする限りにおいて、これはたぶん不当なことだ。彼らの関係性が「異性愛ではない」のは自明なのに、なんで何もかもが異性愛と同じだと考えるかなぁ。フィクションによくあるような、レズビアニズムに男根主義を期待する心性もそうだし。

さてさて、これら性的保守主義は非典型的な性現象のあり方を抑圧する。それらを不自然であると言って攻撃したり、さも選択肢があるかのように「しかるべき場所にいるならいいけど、堂々と一般の場に出てくるな」という。特定の属性を持つが故に職業選択の自由を剥奪されたり自己の心情を表現することを禁じられたりすることの、どこが選択肢なのか。それはゲットーだ。だから、こうした保守主義は非典型的な性のありかた——性的少数者にとって脅威である。性同一性障害の典型例にとっても、基本的には。

誘惑

ただし、性同一性障害の典型例についてだけはこの抑圧からの逃げ道がある。

もともと性的保守主義は性差の本質主義と親和的だ。男と女は生まれつきある程度違っていてだから女がその母性によって子どもを育てるのは自然なことだし、男のほうが数理的能力に優れていて女のほうが感性が繊細で、とかいう。ここで、現代においてはこうした本質主義は、男女では遺伝子やそこからの脳機能の表現型が異なりそれが支配的なのだという主張に等価だ。この主張はある程度までは真実だろうけれども、本当に数理的能力やら言語能力やら、まして育児家事の分担までここから自然に導かれるのかどうかは議論を要する。性的保守主義はこの議論において高次能力や社会的役割にいたるまでかなりの程度自然に導かれるという立場に親和的なのである。そしてここに性同一性障害が登場する。

高次の精神機能の性差が生物学的必然であるとすれば、逆説的にそこには必ず性同一性障害がなければならない。人間の精神、例えば性的自己認知のような複雑な機構が生物学的過程において一件のエラーもなく形作られるなどということはほぼあり得ないからだ。だから性差が生物学的必然ならばエラーによって必ず性同一性障害は発生し、それは本人の選択ではないし、本人に何の責任もない。 つまり性同一性障害の典型例は、性差本質主義を採用すれば厄介な性的保守派からの否定的な視線から保守派自身の主張によって逃れることができる。さらに保守派にとってもメリットはある。性同一性障害者が自己認知と異なる身体や性的役割を受け入れようとして失敗してきた葛藤の深さをして「男女の本質的差異の大きさ」の論拠とすることができる。「" ブレンダ "を見ろ、性同一性障害もそうだ。ただ表層的な身体の形に合わせて自己同一性と異なる性になろうとしても無理だったじゃないか。男は男、女は女、生まれつき決まってるんだ」というわけだ。

性同一性障害の典型例にとってこれは魅力的な誘いである。得られるものは性的保守主義の抑圧からの脱却である。対価は他の後天的・文化的(である可能性のある)性的少数派あるいは男女にくっきりと線を引くことを阻む例、たとえば趣味的異性装者や性的自己認知が男女いずれでもない人に対して保守主義と一緒になってに石を投げることである。つまり性同一性障害の典型例はある種の本質主義に与することによって、性的少数者への抑圧を放置したままに抑圧される側からする側に移ることができる。

性差の本質主義がどの程度真実かは議論の余地がある。そこで本質主義を主張するのは自由だし、主張する人がたまたま性同一性障害であるということもあるだろう。ただそれは非典型的な性現象に対しての差別性を肯定しないはずだ。そして、性同一性障害者が自己の信念に寄ってではなく単に生きるのに楽だからという理由で保守主義の抑圧に荷担するとしたらそれは悲しいことだ。