2009-12-12

twitter より (2009-12-11)

  • ノートパソコンについている「トラックパッド」(で良いのかな?)。マウスの代替としてはなかなかの発明だ(トラックボールからの発展なのかなあ)。けど、iPhone 以降、タッチタイプの液晶画面が(とくに携帯機器において)隆興しているのを見ると思う。(以下、つぎのつぶやきへ) posted at 10:32:22
  • どうして、ノート方でも触れる液晶が主流にならなかったんだろうか、と。 posted at 10:33:28
  • GUI の基本、ユーザに対象物を直接操作している感覚を与える、という方針にのっとれば、画面に直接触れる方が正しい進化であったはず。 posted at 10:35:48
  • すでにマウスによる入力が確立されていたデスクトップと違い、ノートタイプにはマウスとは異なる「何か」が求められていたはず。どうして、トラックパッドのような「いびつなモノ」を作っちゃったんだろう。 posted at 10:38:03
  • コストかなあ。コストのような気がするなあ。 posted at 10:38:29
  • ノート型が一般的になり始めた十数年前には、技術的に難しい点があったのかもな。 posted at 10:41:50
  • Apple がやってくれないかな。次の MacBook あたりで。 posted at 10:42:59

2009-12-11

Cocoa アプリ の構造 #1: Nib の周辺

Cocoa アプリでは、アプリが利用するさまざまなリソースを Nib ファイルに保持している。この中には、アイコン等の画像データに加えて、メニューやウィンドウといったユーザインターフェースの記述もふくまれている。アプリによっては、複数の Nib ファイルを持つものもあり、当然、どの Nib をどういうタイミングでロードするのかを制御する仕組みが存在する。この仕組みが気になり少し調べてみたので、わかった範囲で記録しておく。

アプリと Nib の関係

Cocoa アプリのスタートポイントは NSApplicationMain 関数で、その処理は主に次の 3 つ。

  1. NSApplication のオブジェクトを作ること (グローバル変数 NSApp にセットされる)
  2. アプリの主要 Nib ファイルをロードすること
  3. NSApprun メッセージを送ること

今回、ふと気になって調べたのがこの 2 番目。Nib ファイルのロードについて。具体的には、どの Nib ファイルが、いつロードされるのか、また、そのトリガーは何なのか、など。ちなみに Xcode/Interface Builder 3.0 以降は、デフォルトでバイナリ形式の Nib に代わって XML 形式の「Xib ファイル」が使われる。SCM ツール等との相性の良いテキスト形式のフォーマットを作ったとのこと。ビルドの際に Nib へと変換される。([4]を参照)

まずは、アプリに対して 1 つ存在する「主要 Nib ファイル」というものについて。これはどこで指定しているんだろうか? Xcode で Cocoa アプリ用のプロジェクトテンプレートを指定すると、MainMenu.xib が作られ、これが主要 Nib になる。まさか、ファイル名がハードコードされているはずもないから、どこかに名前の指定があるはず。

主要Nibファイルの設定

[2] の "Changing the Nib Files from the Xcode Defaults" の記述でそれが判明した。Xcode からプロジェクトのターゲットからアプリケーションを選び、「ファイル」>「情報を見る」。「情報」パネルの「プロパティ」タブを開くと、中段に「主要クラス」と「主要Nibファイル」の設定がある (右図)。

ちなみに、これら「プロパティ」の設定は、Info.plist としてアプリにくっついて行く。

MyDocument と Nib の関係

Xcode で document-based アプリ用プロジェクトを作る

Cocoa アプリのプロジェクトを作る際に "document-based application" を指定すると、Document-Based アプリ([3]を参照)を作ることができる。このとき、Xcode が自動生成する Nib ファイルは MainMenu.xibMyDocument.xib の 2 つ。前者は上述のようにアプリの「主要 Nib ファイル」だ。後者はファイルを作成、編集する際に表示するユーザインターフェースを記述するためのもの。では、MyDocument.xib はいつ(何をきっかけとして)、誰が(どのオブジェクトが) ロードするのか? その答えも [3] に書かれていた。以下は、プロジェクトテンプレートが想定する、もっともシンプルな場合の動きだ。

Document-Based アプリでは、NSDocumentController というオブジェクトが存在し、ドキュメントの作成やオープンを担当している。メインメニューからファイルの新規作成やオープンが選択されると、NSDocumentController に指示が届く。で、このオブジェクトは生成する(開く)ドキュメントのタイプに応じて、適切なクラス(NSDocumentのサブクラス; デフォルトでは MyDocument)のオブジェクトを生成する。このオブジェクトとドキュメント編集のための Nib ファイル(MyDocument.xib) との結び付きは、MyDocumentwindowNibName メソッドが返す文字列によって作られる。デフォルトではこれが "MyDocument" となっている。

さて、では NSDocumentController はドキュメントのタイプと MyDocument クラスをどこで結び付けているのだろうか? それも、Info.plist だ。その中で、ドキュメントタイプごとに拡張子やアイコン等と一緒にクラスも指定する。

関連リンク

ちなみに以下のリンクはすべて Mac Dev Center の文書なので、Xcode のドキュメントブラウザからも読める。

[1] Cocoa Fundamentals Guide: The Core Application Architecture on Mac OS X
後ろの方にある "Nib Files and Other Application Resources" が Nib 関連の記述。
[2] Resource Programming Guide: Nib Files
"Anatomy of a Nib File" では、Interface Builder でおなじみの「File's Owner」や「First Responder」の説明がある。
[3] Document-Based Applications Overview: Implementing a Document-Based Application
"The Document-Based Application Project Template" に、Xcode の Document ベースアプリのプロジェクトテンプレートの説明がある。
[4] Interface Builder User Guide: Nib File Management
Nib と Xib の違いについての説明がある。なぜ、Xib ファイルを使うようになったのか、等。

参考文献

ヒレガス本 p.157 に "The Document Architecture" に document-baseed アプリについての簡単な説明がある。ただ、Nib ファイルのことはほとんど何も書いていない。ここに書いていないから、本家のドキュメントを調べたのだ。

Cocoa Programming for Mac OS X
Aaron Hillegass
Addison-Wesley Professional ( 2008-05-15 )
ISBN: 9780321503619
おすすめ度:アマゾンおすすめ度

関連記事

2009-12-10

フリーランチの時代 ([著]小川一水, [版]ハヤカワ文庫JA930) #2

前回に続いて、残りの 2 作品、「千歳の坂も」と「アルワラの潮の音」を読んだ。

収録作品

  • フリーランチの時代
  • Live me Me.
  • Slowlife in Starship
  • 千歳の坂も
  • アルワラの潮の音

千歳の坂も

「千歳の坂も」は、「フリーランチの時代」、「Slowlife in Starship」に続く、もうひとつの豊穣の時代を描く。今度の「豊穣」は不老不死。

むかしから物語に少なからず描かれる不死者は、たいてい偶然に、それも不可避な形で、ほとんど重荷のようにその特性を背負わされる。 しかし、本作で描かれる不老不死は違う。 医療技術が発展した結果、いつの間にか実現してしまったもの。病気が根絶ないしは治療法が確立され、さらには老化遅延さらには防止が可能になった世界。人は、死なずにすむのであれば、誰もがそれを望むのだろうか。死が避け得ない何かでなくなったとき、生きること、生き続けることの意味は変わるのだろうか。そういうトーンで物語は始まる。

本作のおもしろさは、その問いかけだけで終わらなかったところだ。国民に対して不老不死を強制させる役人と、逃れようとする女性。ある意味、体制と個人の自由の対立の構図から始まった物語は、「豊穣」が歪める社会を駆け足で描き出す。いつしか、最初の問いかけは意味を失う。

十分、長編にふくらませることも可能な設定、構想を短編として提供する。千年をわずか数十ページで書き切る。SF 作家はなんとぜいたくなアイデアの使い方をすることか。そして、それを一息で読み切ってしまう SF 読みはさらにぜいたくだ。
(あろうことか、不満を漏らしたりもするからな)

アルワラの潮の音

「アルワラの潮の音」は、「時砂の王」と同じ世界の物語。それも「時砂」の方でナン・マドールの巨石文明における戦いとして言及されているエピソードだ。

(時砂の王; p.231)
南太平洋の島に浮かぶ、半水半陸のその美しい都市で、アレクサンドルと仲間たちが戦ったのは、そう昔のことではない。

「時砂」自体が、ラストはともかく、全体のトーンが重苦しいものだけに、そこで言及されるエピソードも明るいものであるはずもない。この短編を読んだだけでは、その雰囲気が後味の悪さを残すかもしれない。まだ「時砂」を読んでいなければ、これを機会に読んだ方が良い。

もともと「時砂」の物語の設定が、こういうエピソードを数多く挿入できる構成になっている。「勝利三六回、撤退三七〇回」という戦いの中には、まだまだ語られるに足る物語が埋もれているに違いない。シリーズ化しても良いと思うんだよ。それだけ魅力的な設定だ。

参考文献

関連記事

2009-12-09

twitter より (2009-12-08)

  • うお。昨日はなんとなくスルーしてたけど、Google 音声検索すげえ(in iPhone)。 posted at 09:50:22
  • なんか、未来だ、未来を感じるゾ、これ。 posted at 09:50:59
  • 使い方や設定に関しては、このページが詳しい → http://bit.ly/4B56Rf posted at 09:52:48
  • Google Goggles って、AR (augmented reality) の逆だな。→ http://bit.ly/65q4dj posted at 15:45:10
  • AR は実体世界をアッチに取り込むことで機能拡張する。Googole Goggles はアッチの端子を実体世界に伸ばす感じ。 posted at 15:46:29
  • 認識した情報をそのまま検索に投げるだけに使い切るっていうのが、とても Google らしい思い切りだねえ。テキストとして切り出しておいて、そこからユーザに明示的に検索させる(データの編集も可)とかやらないところが、さ。 posted at 15:54:15

2009-12-08

Mac のメニューで良く見る記号

メニュー項目のショートカットキーを表す記号の一覧を Xcode のドキュメントで見つけたので、抜粋してみる。[Option]、[Shift]、それに [Control] は修飾キーと呼ばれ、ショートカットキーの一部として良く見かけるもの。そのくせ、近頃の Apple のキーボードには記号による刻印がないため、どれがどれだかわからなかった。この表があればもう迷うことはない。

KeySymbolUnicode code point
Command (Apple)U+2318
Option (Opt/Alt)U+2325
Control (Ctrl)U+2303
ShiftU+21E7
Escape (Esc)U+238B
BackspaceU+232B
DeleteU+2326

ちなみに、アップルメニュー(メインメニューの左端)のリンゴマークは [Shift] + [Option] + [K] で入力できる。これがその記号「」。Unicode の U+F8FF に割りあてられている。これは私用領域(U+E000 - U+F8FF; Private Use Area)の一部で、いわゆる外字になる。よって、Mac 以外では表示できない(はず)。これが Windows では「窓マーク」になっていたらオモシロイんだけどね。
(GNU/Linux ならペンギン、BSD系ならデーモン……って、そんなフォントないか)

関連リンク

2009-12-07

文字列参照の変換 (つづき)

先日、テキストに混じった数値文字列参照(あ という形式のもの)を元の文字に変換することについて書いた。そのとき、一応動くものができたけどきちんと変換できているか不安だ、とも書いた。今回は、それを実際に確認することから始めて、文字の取り扱いについて、少し調べてみた。その結果を書き留めておく。全体の流れはこう(↓)なる。

  1. 変換が成功していることを確認する
  2. Unicode について少し調べた
  3. 各種プラットフォームでの文字の取り扱いの差

変換が成功していることを確認する

まずは変換が成功することをどう確認するかを考えた。文字コードやらその取り扱いについて調べると時間がかかりそうなので、もっと直接的に(かつ、愚直な方法で)やることにした。

  1. 元のテキストから数値文字参照を抽出する
  2. 抽出した数値文字参照の文字列を 1 行につき 1 つずつ書き出す
  3. sort して uniq する
  4. 変換プログラムにかける
  5. 結果を視認でチェックする

1 〜 4 までが直接的(かつスマート)な部分で、5 が愚直な方法。

1 と 2 は 1 つのごく短い Ruby プログラム。標準入力から読んで、標準出力に書き出すシンプルなフィルタになっている。前に書いた変換プログラムをちょこっと修正しただけ。10 行目でおかしなことをしているけどキニシナイ。

(pickp_numrefs.rb)
 1: #!/opt/local/bin/ruby1.9 -w
 2: # coding: utf-8
 3: 
 4: pattern = /&#[1-9][0-9]*;/
 5: 
 6: STDIN.each do |line|
 7:   while pattern === line
 8:     numref = Regexp.last_match[0]
 9:     STDOUT.puts numref
10:     line[numref] = "*"
11:   end
12: end

元のテキストを cat で、こいつに流し込んで、出てきたものを sort | uniq にパイプでつなぐ (上記のステップ 3 と 4)。

変換プログラムも前のものを流用。

(print_numrefs.rb)
 1: #!/opt/local/bin/ruby1.9 -w
 2: # coding: utf-8
 3: 
 4: def convert(ref)
 5:   num = ref[2...-1].to_i  # Numerical reference must be "〹"
 6:   fs = "%c".encode("UTF-8")
 7:   fs % num
 8: end
 9: 
10: STDIN.each do |numref|
11:   STDOUT.puts "#{numref.chomp} -> #{convert(numref)}"
12: end

最終出力はこんな感じ(↓)。「丑」なんて文字、入っているはずがない、と思って調べてみると「土用の丑」という言葉の一部だった。

[...snip...]
一 -> 一
万 -> 万
丈 -> 丈
三 -> 三
上 -> 上
下 -> 下
不 -> 不
与 -> 与
丑 -> 丑
[...snip...]

結局、1514 種類の数値参照が混じっていた。一文字、一文字、丹念にチェックしたわけではないが、少なくとも豆腐印になっている文字はなかった。

Unicode について少し調べた

Wikipedia (ja) を中心に Unicode やら ISO 10646 のことやら調べてみた。わかったのは、だいたいこんなところ(↓):

  • 現在の Unicode 規格は Version 5.2.0 で、2009-10-21 にリリースされた
  • 当初、16 ビットで世界の全ての文字を符号化(番号づけだね)しようとしたが、番号が不足したため、現在は 21 ビットで規定されている
  • もとの 16 ビット領域 (U+0000 〜 U+FFFF) は Unicode 2.0 以降では BMP と呼ぶ
  • BMP は ISO/IEC 10646 の UCS-2 (16ビット範囲) と同一(番号も同じ)
  • 一方、ISO/IEC 10646 の UCS-4 (31ビットの文字集合) とは別物
  • 日本語で使われる「かな」は U+3040 〜 U+30FF で定義されている
  • 普段使う漢字はほぼ U+4E00 〜 U+9FFF の範囲にある (CJK統合漢字)
  • 16 ビットの上位 9 ビットが 0 の U+0000 〜 U+007F は ASCII 互換

そしてふと思い出した。Matz の「コードの世界」に文字コードについて書いてあったことを。早速、読んでみた。うん、わかりやすい。読み物としてまとまっている方が理解しやすい。「文字コード」という用語があいまいに使われていることについての言及もあり、「文字集合」「文字コード」そして「符号化方式」の意味の違いが簡潔にまとめられている(→ p.181)。

ちなみに、Wikipedia の Unicode の項には Unicode 一覧へのリンクがある。これは Unicode 文字を 4096 文字ごとにコードポイントの順番に並べた表で、どのコードポイントがどういう文字なのかが一目でわかる。作った人に感謝。

各種プラットフォームでの文字の取り扱いの差

「コードの世界」でも言及されているが(p.196 〜 202)、プラットフォーム(プログラミング環境)によって文字の取り扱いに差がある。(わたしにとっての)主要なプラットフォームについて、文字の取り扱いに関する特徴をまとめてみる。

Ruby 1.9

「コードの世界」で言うところの、CSI (Character Set Independent) 方式。UTF-8 などの符号化方式を指定すれば Unicode 文字を扱える。先日の数値文字参照の変換が、単なる数値から文字への変換でできたのは、このおかげだ。つまり、UTF-8 を指定した文字列に対して、Unicode 文字の「文字コード」すなわち Unicode のコードポイントを与えてやれば、適切に UTF-8 に変換される。

もともと、わたしが変換しようとしたデータのオリジナルは自分で書いた文書だ。オリジナルの状態でどういう符号化方式で保持されていたにせよ(UTF-8 だったはず)、適切に数値文字参照に変換されていたならば、その数値は Unicode のコードポイント (正確には ISO 10646 のもの) であるはず。そこで間違いが入り込んでいない限り、先のプログラムで正しく変換できることになる。愚直な方法でやった確認に関して、理論的な裏付けが得られたわけだ。

Mac OS X (Objective-C/Cocoa)

Ruby とは異なり、Mac OS X の Objective-C の文字列は UTF-16 になっている。「コードの世界」で言う UCS (Universal Character Set) 方式だ。Java や Python と同じ方式ってこと。

(Mac Dev Center: String Programming Guide for Cocoa: Strings より)
A string object is implemented as an array of Unicode characters (in other words, a text string).

ここで言う「Unicode characters」は「文字集合」ではなくて「文字コード」のことになる。ちょっと調べた程度では、16 ビットを越えるコードポイントの文字をどう扱うのかまではわからなかった。NSString オブジェクトを lengthcharacterAtIndex: を経由して扱う限り、その領域も正しく扱えるのだろう。今は、あまり深入りしないでおこう。

Gauche

プログラミング Gauche」には、こう書かれている。

(5.2 マルチバイト文字の利用 より)
Gauche はマルチバイト文字をサポートしているので、プログラム中の文字列やコメント、変数名に日本語を使うことができます。
(・・・中略・・・)
ただし、ASCII 以外の文字を使う場合、文字コードに気をつける必要があります。
デフォルトでは、Gauche はビルド時に決定される内部エンコーディングでプログラムが書かれていると考えます。

あれ、これってどっち方式だろう(・ω・)?

Gauche の公式サイトには、作者自身による文字列の取り扱いに関するデザインメモが置かれている。こういうプログラマの意図がわかる情報は貴重だ。

せっかく mini に Gauche をインストールしたことでもあるし、先日の変換プログラムを Gauche で書いてみよう。今日じゃないけど。そのうち。Gauche はもともと、

(Gauche ユーザリファレンス: 1.1 Gauche の概要 より)
Gaucheは、プログラマやシステム管理者がこなす日常の雑事を効率よくSchemeで書けるようにすることを目的として設計されています。

ということだから、ああいうフィルタなんかも書きやすいはず。

関連リンク

参考文献

関連記事

2009-12-06

Gauche 0.9 をインストール

Mac mini (Snow Leopard Server) に Gauche の最新版を インストールしてみた。Ports が少し古いバージョン対応のものなので、Portfiles をちょいちょいと書き換えて、インチキ ports としてインストール。Gauche 用の Portfiles は /opt/local/var/macports/sources/rsync.macports.org/release/ports/lang/gauche にある。

Portfiles の変更点はこんな感じ(↓):

  1. Version を 0.9 に。
  2. checksums を再計算した値に。
  3. patchfiles は不要なので、行ごと削除

ちなみに、checksum の再計算は以下のように実行する (MacPorts Guide より)。md5 は md5 で、あとの 2 つは openssl に計算のタイプを指定して行う。

[mini:~] mnbi% md5 Gauche-0.9.tgz 
MD5 (Gauche-0.9.tgz) = 1ab7e09da8436950989efd55b5dc270a
[mini:~] mnbi% openssl sha1 Gauche-0.9.tgz 
SHA1(Gauche-0.9.tgz)= ebc18917c36201d6c3fda29dfdc52fce2d856a5f
[mini:~] mnbi% openssl rmd160 Gauche-0.9.tgz
RIPEMD160(Gauche-0.9.tgz)= 3e0dfc1d498849b0d647e13f49addd0a56cc56fe

configure のオプションはともかくとして、patch の適用の有無はさすがに不安なので、port とは関係なしに、configuremakemake test して確認した。そのときの configure がこれ (行を "\" で折り返してある)。

./configure --mandir=/opt/local/share/man \
            --infodir=/opt/local/share/info \
            --with-local=/opt/local \
            --enable-multibyte=utf-8 \
            --with-iconv=/opt/local \
            --with-slib=/opt/local/lib/slib \
            --enable-threads=pthreads \
            --enable-ipv6

オリジナルの Portfiles にあった設定そのままを手動で実行したことになる。 この設定で make の後、make test をした結果がこれ(↓)。全テスト合格。

Total: 10076 tests, 10076 passed,     0 failed,     0 aborted.

インチキ ports を使ったインストールの実行結果は以下のとおり。

[mini:~] mnbi% time sudo port install gauche
--->  Computing dependencies for gauche
[...snip...]
--->  Installing gauche @0.9_0
--->  Activating gauche @0.9_0
--->  Cleaning gauche
126.559u 33.476s 1:58.65 134.8% 0+0k 233+860io 0pf+0w
[mini:~] mnbi% rehash
[mini:~] mnbi% which gosh
/opt/local/bin/gosh
[mini:~] mnbi% gosh -V
Gauche scheme shell, version 0.9 [utf-8,pthreads], i386-apple-darwin10.2.0

Gauche 0.9 に付いてくる configure を見ると、Portfiles で指定されている gdbmlibiconvslib に加えて、zlib にも依存している。依存関係に追加すべきか迷ったが、Snow Leopard 標準の zlib も、ports のものもバージョンが同じようだったので、気にしないことにした。

関連リンク

  • MacPorts Guide (チェックサムの計算については、4.2 Creating a Portfile のステップ 13 を参照)

参考文献

プログラミングGauche
プロジェクト
オライリージャパン ( 2008-03-14 )
ISBN: 9784873113487
おすすめ度:アマゾンおすすめ度

関連記事

MacBook にも Ruby 1.9 をインストール

mini のときと同じく実行結果だけ。

[book:~] mnbi% time sudo port install ruby19
--->  Computing dependencies for ruby19
--->  Fetching ruby19
[...snip...]
--->  Installing ruby19 @1.9.1-p243_0
--->  Activating ruby19 @1.9.1-p243_0
--->  Cleaning ruby19
247.197u 51.410s 4:35.89 108.2% 0+0k 44+5904io 0pf+0w
[book:~] mnbi% rehash
[book:~] mnbi% which ruby1.9 
/opt/local/bin/ruby1.9
[book:~] mnbi% ruby1.9 -v
ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]