猫の小部屋 - ねこのこべや -

猫日誌 -2005-


2005年03月

1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

Topics

>>> [index] [next] [prev]


03月25日(金)

なんだか講義とはほど遠いすがたになってきました。 体系立てて紹介する手間が面倒くさくなってきたのと言うのが真相です。

ふたつの永続化 (ぬくぬくPython #5)

ファイル指向なOSの上で オブジェクト指向な言語を作ると 次の問題に必ず直面します。

  • オブジェクトの永続化されない(実行終了の度 オブジェクティブ・ワールドごと消える)
  • オブジェクトを作るコードをオブジェクトに出来ない(ファイルになる)

ファイル指向OSの中でメモリの上だけでオブジェクトワールドを作ると言うことは、 プログラムを終了するとオブジェクトがすべて消えてしまうと言うことです。 言い換えれば眠る度に世界が消えてしまうのです。

コレの解決策としては、 OSを作ってしまえっ!がもっとも強力且つシンプルです。 (これをバーチャルマシンと言います。 そういう意味ではJavaのVMは微妙です。)

Smalltalkのようにオブジェクトメモリがすべての世界(OS)を作ってしまうのが 一番といえば一番なのですが、現実問題としてなかなかそういうわけにはいきません。 ファイル指向OSの中で「ツールとしての言語」であるためには 永続化はファイルでなければなりません。

さて、われらがPythonはどのように折り合いをつけているかというと、 言語的に定義された「モジュール」と、オブジェクトを永続化するpickleモジュールが肝です。

モジュール

まずはクラスオブジェクトの永続化からみましょう。 すなわち実行ファイルまたはそれのソースファイルが オブジェクトワールドでのどのオブジェクトに見立てられるか、ということです。

Javaの場合「ファイル」を「クラス」に見立てる作戦を取っています。 publicなクラスを定義したコードを一つのファイルとすることで、 クラスオブジェクトと見立てているのです。 (ついてにバイトコンパイルしたオブジェクトもpublicなクラスごとです)

この作戦はそれなりに意味があるものの、 ファイルとオブジェクトの粒度の違いから、なかなか扱いにくいのも現状です。 つまり、ファイルのほうがオブジェクトより通常大きなモノをあつかうので、 逆に同じ程度の複雑さのモノに相対すると数が少なくてすむのです。 この感覚の違いは実は思った以上にやっかいで、 オブジェクト指向設計に悪い影響を与えることすら有ります。 (心理的にクラスの肥大化を招いてしまう場合がある) またクラス名とファイル名を合わせる仕事は人間がやらなくてはならないのも、 とてもかったるいモノです。

一方 Javaのライバル C# では、オブジェクトワールドでの実体と ファイルワールドでの実体の間に何の関連もありません。 クラスですら複数ファイルに分けて書くことも、 逆にたくさんのクラスを一つのファイルに入れることも出来ます。 Javaのようにフォルダがパッケージになることもありません。 すべてはソースコード上での記述のみで、 そこにファイルワールドの構造が持ち込まれる余地はありません。

これも、下手に同期させるくらいなら・・という良いアイデアだとは思うのですが それでも、完全に頭を切り換えろというのはつらいことだと猫は思ってしまいます。

そこで我らが Pythonでは、Pythonワールドでの「モジュール」をOS世界でのファイルにマッピングします。

Pythonコードの書いてあるファイルは、 Pythonワールドに突入すると、そのまま「モジュール」という姿に形を変えます。 モジュール名はコードファイルのファイル名から拡張子「.py」を取り除いたものになります。 モジュールはクラスをコレクションできる規模のオブジェクトで、 ファイルの粒度と同じくらいであるというのが扱いやすく感じます。

これは猫にはもっともバランスの良い解決策に思えるのです。

ピクる。

では、クラスオブジェクトではなくてインスタンスオブジェクトの方の永続化は どうするのかというと、当然ファイル指向のOSの世界では オブジェクトのスナップショットをファイルとして書き出すしか有りません。

Pythonではこれを行うモジュールが用意されています。 pickleという名前のモジュールです。 これ、どういう意味かというと、ハンバーガーなんかに挟まれているアレ、ピクルスなのです。

ピクルスはようするに漬け物です。 オブジェクトがメモリに居る以上、鮮度(?)が肝心、 いつまでもメモリ上に出しておくといつかは腐って無くなってしまう(^^;)のです。 ずっと取っておきたければ漬け物にするしか有りません。

なので、オブジェクトをファイルに永続化することを「ピクルス化」、 元に戻すことを「逆ピクルス化」と言います。 (Pythonが日本で出来ていたら「ぬか漬け」になっていたに違いない・・)

概念としては、ファイルというヌカミソにオブジェクトを漬け込んで 保存する・・・といいう発想です。

さて、サンプルとしてぬか漬けするためのユーザ定義型 を定義しましょう。

NatumeNeko.py
class neko: """ 猫クラスです。 この猫は夏目漱石の猫なので、 時代がかった口調で自己紹介をします。 """ def __init__(self): self.name = "まだ無い" def set_name(self ,new_name ) """ 新しい名前を設定します。 """ self.name = new_name def say_myself(self): """ 自己紹介を行います """ print "吾輩は猫である。名前は、" + self.name

このクラス neko のインスタンスオブジェクトを ぬか漬けします。

NekoPickle.py
import pickle from NatumeNeko import * # 漬け込む対象を作る mineko = neko() mineko.set_name( "三猫" ) # ピクルス化 afile = open( "nukaduke.hoge" , "wb" ) # 漬け込み樽の準備(永続化対象ファイルオープン) pickle.dump( mineko , afile ) # 樽に漬け込み

この操作により、変数minekoに束縛されていたオブジェクトは、 nukaduke.hoge ファイルにぬか漬けされました。

NekoUnpickle.py
import pickle from NatumeNeko import * #ピクルスからサルベージ someneko = pickle.load( "nukaduke.hoge" ) # 復元出来たか確認 someneko.say_myself()

これを実行すると、say_myself()の実行結果として、 コンソールに「吾輩は猫である。名前は、三猫」が出力されます。 見事三猫はぬか漬けから生還したわけです。

もっとピクる。

猫一匹漬け込んだところで面白くも何ともありません。 もっとたくさん浸けてみましょう。

# 漬け込む対象を作る -------------------

# 三猫
mineko = neko()
mineko.set_name( "三猫" )

# タマ
tama = neko()
tama.set_name( "タマ" )

# 名無し猫
nanashi = neko()


#3匹まとめて配列に。--------------------
cats	= [ mineko , tama , nanashi ]


# ピクルス化 ---------------------------
afile    = open( "nukaduke.hoge" , "wb" )         # 漬け込み樽の準備(永続化対象ファイルオープン)
pickle.dump( mineko , afile )                     # 樽に漬け込み

これをまとめて復帰させます。

import pickle
from NatumeNeko import *

#ピクルスからサルベージ
nekolist = pickle.load( "nukaduke.hoge" )

# 復元出来たか確認
for someneko in nekolist:
    someneko.say_myself()

この結果として、「我が輩は猫である。名前は、三猫」「我が輩は猫である。名前は、タマ」「吾輩は猫である。名前は、まだ無い」 とコンソールに出力されます。 これは便利です♪

|++ month top ++|

03月24日(木)

最近自身の文章のくどさに、 辟易としています。あたしってダメだわ〜。

発見! 構造化プログラミングの良い説明

猫はうまい説明を探して、いっぱい文章を打ってきたのですが 全然わかりやすくもないし、読みにくいです。

たとえば「構造化プログラミング」の説明には 猫は何度もトライしてるのですが一度たりとも勝利(?)を収めたことがありません。

そんななか、昨日の日誌でとりあげた「ソフトウェアの20世紀」に とても良い表現が 載っているのを見つけました。

アルゴリズム(aligorism)は代数学的に“算法”などと訳されるが、 プログラミングでは“問題解決の手順または手法”という意味合いになる。

問題を解決する手順をプログラムとしてコード化するということは、 アルゴリズムを明快に記述するということにほかならない。

そのためには分類・整理された現実の事象とそれらに対する扱い方を、 個別の処理単位としてくくることができなければならない。

これを、プログラムの“構造化”という。

素敵です。簡潔でわかりやすく、ポイントを押さえています。こういう風に表現したかったのよ、あたし。 やっぱりプロはちがいますね〜。 猫もこういう簡潔で解りやすい文章が書けるようになりたいです。

新人研修テキストはこれを 流用させて頂だこうかしら、なぁんて思ってます。

|++ month top ++|

03月23日(水)

今月の猫日誌はやたらめったらオブジェクト指向とそのコンピュータ史ばかりです。 新人教育に「オブジェクト指向の概要」とか言う玉虫色の講義を割り当てられてしまった猫は 自分の考えをまとめるために猫日誌にガンガンつづっていってるのですが、 考えながら書いているため支離滅裂です。 (それでいて電車の中とか休憩時間とかで書いているから 考え自体がとぎれているし・・・)

また、自分で書いておいて嘘ばっかで間違いだらけなのも気になります。 知ったか知識にすぎないのがバレバレなのです。

でも正確に書こうとするとまたそれはそれで問題があります。 「ホント」ってなにかしら、ということです。

コンピュータ史がバグだらけ

コンピュータの歴史は20世紀の出来事なので、 歴史的人物のほとんどが生きていますし、時代も近いので資料もたくさんある ・・・はずなのですが、こうもいい加減なのはなぜでしょう。

手始めに、ソフトウェアの20世紀Old Good COMPUTER!を読み比べてみてください。 この結構な内容の相違はなんなのかしら(TT

「ソフトウェアの20世紀」は書籍で、上のWebからも読めるものです。 一報 「Old Good COMPUTER!」 は 魔法使いの森さんのコンテンツで 個人サイトです。 世間一般的には 「ソフトウェアの20世紀」のほうが正しいと思われがちですが、 猫にはどうしても「Old Good COMPUTER!」の方が正しく感じます。 というのも「ソフトウェアの20世紀」はコンピュータ史の伝説がそのまま乗っているのですが、 この手の伝説は誇張や都市伝説のようなものになってしまっていて、 鵜呑みにするのは危険です。

ふぉーえぐざんぷる

たとえばゼロックスのパロアルト研究所で「Alt」というマシンを見た スティーブ・ジョブスとビル・ゲイツが GUIなOSをパロディしたというのが「伝説」ですが、 この伝説を語るときに「Alt OS」なるモノを想像しがちです。 で、その創作がそのまま「ソフトウェア史」の文章として残ってしまう・・。う〜、、捏造連鎖です。

実際にはそこで動いていたのはSmalltalkであったと言われます。 Smalltalkは「元祖オブジェクト指向言語」というレッテルが張られているのですが、 Smalltalkは言語仕様であり、環境(OS)でもあるのは意外に知られていません。

で、ここからは更に複雑なのですが、この「GUI-OSはSmalltalkが作った伝説」も、 Alto、Star、Smalltalk、Lisa、Mac の関係をはっきりさせようを見ると 怪しいランプが灯り始めます。

・・・

ここまでくると、一体何が本当なのかさっぱりわかりません。

結構毛だらけ、猫、間違いだらけ

コンピュータの、ソフトウェアのジャンルは巨大で、 結局網羅的なものをまとめようとすると「伝聞」に頼らざるを得ないけれど、 その伝聞がかなりの規模と確立でゆがんでいます。 だからコンピュータに冠する広範囲・網羅的な情報は、かなりの確立で間違いを含んでいると 思っても良いのかもしれません。

コンピュータの進化って「ミーム」的な遺伝のとても良い例だと猫は思います。 Hoge言語はHoge言語を作った人の知識と好みの全てが影響しているわけです。 網羅的な情報、系統や進化、歴史などを扱おうとすると、 あまたの関係者達の全てをたどって行かなくてはならないのですがそんなことはムリです。

どんなことにも言えますが、「10年後のキーとなる技術」を登場時の人が 正確に評価するのは難しいです。 また、「専門化」が進んでいるため、一般にのための説明を 専門の人じゃない人が作る機会も多くって、そう言う場合「間違っていないけど合っても居ない」 解説になりがちです。 なので、コンピュータ技術への評価は現在・過去を問わず間違いだらけです。

たとえば過去、 Lispが「人工知能用」という説明は未だに良く聞かれますが、 用途から言語を説明するならば、まだ「Emacsというテキストエディタのスクリプト言語」の方が 実態に即しています。(そしてそう言う説明のしかたも本質ではないです)

そして現在、 javascriptがプロトタイプベースのオブジェクト指向言語だということを 知っている人がどれだけいると言うのでしょうか。 (それ以前にクラスの無いオブジェクト指向言語が有ることをどれだけの人が知っているのかしら)

偉そうに言うけれど

ハイ、猫も間違いだらけの一人です。 このページには自分でも突っ込める間違いも多いですが、 自分では正しいと思っている間違いも多いことは想像に難くありません。 100や200の間違いで追いつかないような気もします(^^;

いつもどおり取り留めのない文章ですが、 結論は一つ。今ならまだ人も生きてますし実機も資料も残ってます。 コンピュータ史の研究者さんには最大にして最後のチャンス。 ぜひぜひ頑張って欲しいわぁ、と。 ――そして普通の人が「定説」を語ればほぼ間違ってないという 感じになって欲しいわぁ、と。

おまけ

と、「間違いだらけはいけないわ」な本文を書いておいて とても恥ずかしいのですが、先月の猫日誌で 超弩級の間違いを発見。

C++の設計者 ビョーン・ストラウスさんによる...

だ、誰よコレ・・・。

正しくはビ・ストラウストラップさんです。 全然違います。(^^;) きっとコレを書いたとき猫の脳は壊れていたに違いない・・・。

と、言うわけでこっそり直しておいたけれど どうにもこうにもな決まりの悪さをごまかすためのコラムでしたとさ。

|++ month top ++|

03月22日(火)

Pythonのデータ構造をちょっとだけ (ぬくぬくPython #4)

「Pythonのデータ構造」という表題ですが、 今回は「言っていることは解るんだけど 何のためにあるのか解らない」と評判のタプルだけです。

だって他は大体想像が付きそうなんだもの・・。 (と、自分に言い訳) ――手抜きです・・・。

タプル

Pythonの組み込みデータ型のうち、 最も「ピンとこない」のがタプルじゃないでしょうか。 もちろん「変更不可能な順番のあるコレクション」、という 説明自体が解らないということは無いのですが、 何のために使うのかピンとこないんです。

だって要素を変更できるリスト(「[]」で囲む奴 )があれば必要ないですし、 Pythonの3大組み込みコレクションのなかで唯一メソッドを持たない、 つまりコード上で一度書いちゃったら、その組は変更出来ないなんて不便な存在、 何のために必要あるのかしら。

と、思うのはとてももっともだと猫もおもうのですが、 「コードで一度書いちゃったら」という所にヒントがあります。 実はタプルはソースコードの為にあるのです。 タプルの存在はソースコードに柔軟さを与えます。 以下のサンプルを見てください。

def Hoge( a, b, c ):
    """
    引数で与えられた3つのオブジェクトを
    逆順にして返します
    """
    return c, b, a


a, b, c = Hoge( 'あ', 'い', 'う' )

print a, b, c
う い あ

このコードを見ると「えっ! Pythonって 複数の値をリターン出来るの!?」と思ってしまいます。 でもフフン♪ これはタプルの仕業なんです。

これは 「print文の文字列結合演算子は『,』なのね」と言うことではありません。 print文に与えられているのは 三つの文字列オブジェクトではなくて、 一つのタプルです。 試しに直接戻り値をprint文に渡すと、

print Hoge( 'あ', 'い', 'う' )
('う', 'い', 'あ')

の様に 出力書式からタプルであることが解ります。

以上から見て解るとおり、タプルのシンタクスは 「()」で囲う必要はありません。 タプルのシンタックスは「,」で区切りそのもので、 リストやディクショナリ、print文などカンマ区切りが 「別の意味」になるところでは 「()」で囲ってあげる必要がある、 というのが多分ホントのところです。

タプルを使っている例で有名どころをもう一つ上げると、 前に紹介したprint文の文字列フォーマットがありますね。 タプルはコードという「ロジックのリテラル表記」の中に埋め込まれた コレクションを表現するのに有意義な存在――だとあたしは思います。

|++ month top ++|

03月20日(日)

前回あれだけ散財して財布の紐を締めなきゃ、と 行っていた矢先にドカンと大散財をしてしまいました。 うう、既にもう猫の支払い能力を超えてまする・・・(TT)

ああ、猫の人生はこれからどうなってしまうのでしょうかっ!! こうご期待ですっ!

追散財

なんだかMac miniが呼び水になってしまいました・・・。

Happy Hacking Keyboard Professional 無刻印

じゃんっ♪

Happy Hacking Keyboard Professional
Happy Hacking Keyboard Professional

Mac miniを買ったらとても欲しくなっちゃいました。

だって、日本語キーボード上手く認識しないですし、 なによりもテンキーレスキーボードすら巨大に見えてしまう小型ボディ・・。 うあ、買いたいフラグが立っちゃったです。(笑) もちろんMacとあわせるなら無刻印の白よね!!!

凄く良いキーボードなんですが、2万4000円は痛いわぁ・・・。

お金を大切にね♪・・・うう(TT)

Happy Hacking Keyboard Lite

HHK Proを買った矢先にコレを買ってしまいました。 だって秋葉原の某店で中古で2000円だったのですもの・・。

HHK Proの無刻印をかった猫は困ったことに 配列が全然わからなかったのです。 特に日頃日本語キーボードを使っているので記号類が 移動してしまったのが辛い。 プログラマの猫には 「(」「)」「"」「'」の移動が身を切るよう痛いです・・・。(TT) そんなわけでLite君にはキーボード配列表として頑張って頂いてます。 (・・ああ、なんてもったいない)

しかしLite2も良いのですがココはやはりLiteでしょう。 なんといってもカーソルキーがありません。

猫は Mac に Carbon Emacsという テキストエディタを入れて使っているのですが、 このテキストエディタはカーソル移動を、 「Ctrl-F」(=→)、「Ctrl-B」(=←)、「Ctrl-P」(=↑)、「Ctrl-N」(=↓)で 出来るので、今のところHHKのカーソル移動には猫はなれていません。 こんな段階でHHK Lite 2なんて買った日にはアナタ、 一生HHKのカーソル移動が身に付きません。

PS/2接続専用ということで、 ノートPC三昧の猫の今のPCライフではどこまで使って上げられるかわからないのですが、 Liteも一度じっくり語り合ってみたいキーボードです。 と、言うのも、スライダ・スライダのレールこそキートップ・筐体一体形成だったりしますが、 中は金属板を配したなかなかしっかりした構成になっていて、 これはこれで「Lite って廉価版でしょ、打鍵感だって・・」と 一概に切り捨てるようなキーボードでは無いからです。(実はChicony製です。)

とかいいつつ、「写真取るからお掃除、お掃除〜♪」してたら キーを一つ無くしてしまいました。ううう、、今月は厄月だわ・・。

スピーカ

一言で言って失敗しました(TT) Edifier というメーカのR1800TNという機種です。

Edifir R1800TN
Edifir R1800TN

秋葉原のジャンパラで売っているのですが、 店頭で聞いた限りでは平穏が良く響いて、とても高い音が綺麗になるので、 「これで4000円代は安いわぁ」と思ったのですが、 いざ家に帰って聞いてみると 中音域がぼけてしまい、女性ボーカルのPOPなんかを聞くと、 伴奏がズカズカキンキンうるさいのに ボーカルがちっとも聞こえない。クリアボイスは濁ってしまう・・・。

中音域が弱いということで、じゃあ安めのスピーカ買ってきて 同時にならせばいいじゃない、と買ってきたのがコレ、 エレコムの「木のスピーカ」の安い方、 MS-75PI です。

ELECOM MS-75PI
ELECOM MS-75PI

で、実際試してみたら々だったかというと・・・ダメダメでした。 考えてみれば、「足し算したら綺麗にバランスが整う」なんて 上手いこと行くわけありません。ああ、疲れていたのかしら・・・。

と、いうわけで結局猫にとってはゴミの山を作り上げただけの お買い物になってしまいました。 うう、、久しぶりに大失敗です(TT)

技術書またたび

[復刻版]オブジェクト指向ソフトウェア工学 [OOSE]
オブジェクト指向ソフトウェア工学
オブジェクト指向ソフトウェア工学

とてもとても欲しかった本です。スリー・アミーゴの一人、 イヴァー・ヤコブソンさんの書いたOOSEです。

オブジェクト指向自体は SimulaやSmalltalkを源泉とする70年代に端を発する出来事なのですが、 ここまで広まったのは このOOSEやBooch方、OMTといった オブジェクト指向分析設計やそれに基づくシステム開発が 敷衍したからです。

原著は92年に発刊されていて、その後の世の中のプログラミングを変えた歴史的な本だったりして、 猫はずっとずっと欲しかったのです。 最近(?) Goodな本を一杯リリースしていて オライリーやピアソンのようなブランドが にわかに立ってきた感のあるSIBアクセスさんによる 復刻なのですが、普通の書店には並んでません。(Amazon.co.jpだって売ってません) というのもオンデマンド出版だから、注文するとつくる形態で販売されているのです。

とはいえ、お店がまとめて注文買い取りしちゃえばOKということで(たぶん) 秋葉原のLAOXで店頭販売してまして、 一冊、また一冊と無くなるプレッシャーに負けての購入です。

内容はとても良いです。13年前の本だとは思えません。

Unix for Mac OS X 第三版
Unix for Mac OS X
Unix for Mac OS X

せっかくMacを買ったので、日頃あんまり使いこなせてないUnix系OSのお勉強をしようかと思い 買ったのですが、 インストールガイドとシェルの解説といった内容で、 もっと濃い内容を想像してた猫にはちょっとアレレな感じでした。

とはいえ良くできた本です。 Unix系OSにまったく触ったことがない人で、 興味とMacがある人にはおすすめです。

Running Mac OS X
Running Mac OS X
Running Mac OS X

そんなわけで、もうちょっと濃い Unix in Mac な本です。 中級者向けとここと。猫にはピッタリです。

プログラミングまで行かないけれど 十分Unixを堪能したい人にはお薦めの一冊です。

ANCI Common Lisp
ANCI Common Lisp
ANCI Common Lisp

ポール・グレアムさんのLispの本。名著です。

しかし、先月Schemeの本を買ったばかりで連チャンで買うことはないとは思うのです。 しかし猫の癖として「読む暇なくても読みたい本をとりあえずかっとく」のがあるのです。 「朝電車で本を読めそうな体調のとき」とか 「休日 ノートPCと本を持って喫茶店に行きたいとき」に自分の本棚に読みたい未読の本がいっぱい無いと 困ってしまいます。

そんな贅沢な生活を猫はとても気に入っているのですが、 お財布と床が心配で夜も眠れません。

コンパイラの理論と実践
コンパイラの理論と実践
コンパイラの理論と実践

先月の散在で買った 「スモールコンパイラの制作で学ぶプログラムのしくみ」ですが、 Rubyの作者 まつもとゆきひろさんちの日記で 読みやすくて良いのではと書いてあるのを発見。 そうかぁ、良い本だったですか・・。

猫のパラパラ読感では微妙と言ってしまったのだけれど 大御所がいうなら内容的にヤバげなところはないかなぁと。 じゃあ、この直感と実際の違いはなにかしら、と思うに そこが文系と理系? というわけで、 比較用として理系なコンパイラの簡単本を購入しました。

猫は文系・理系というのは迷信だとおもっているのですが、 迷信じゃないとすると、構造化された文章と ストリームな文章のどちらを好むかということなのかもしれない、ともおもったり。 つまり理解せずに読み進めることを気持ち悪いと思わないことが決定的なちかいかしらね、とか。

そしてこの本は買ったけれどまだ読んでいないのでした。

マンガまたたび

懲りずに買いまくり。 まんが紹介はなぜだかすこし評判だったので 今回はより オススメ & デンジャラスをチョイス。 攻めの姿勢です。(笑い)

フリー・ソウル
フリー・ソウル
フリー・ソウル

やまじえびね さんの最新作です。ねこはこの人のマンガ大好きです。

やまじえびね さんはビアンのマンガを書かれる方です。 そういうのがダメでないなら是非オススメします。

今回はえびねさん(で区切っていいのかしら)のマンガとしては 性表現がちょっとだけ過激でちょっとビックリです。

ちなみに表紙のスキンヘッドのお姉さんは作中マンガのキャラクタです。 作中の女の子達はボーイッシュじゃないですよ。

トリバコハウス
トリバコハウス
トリバコハウス

宇仁田ゆみさんの 漫画は実は「トリバコハウス」を除いて みんな持っているのですが、退屈なときのための「とっておき」として 買わないでおいたのです。

が、酔った勢いでいつの間にかにかっていました。 うう、ダメ猫だわ〜。

猫は宇仁田さんの漫画が大好きなのですが、 一番好きなのはマニマニかしら。もちろんトリバコハウスもとてもおもしろかったです。 (て、小学生の読書感想文みたいなコメントです。)

スーパーダブル
スーパーダブル
スーパーダブル

星野リリィさんは普段はやおいですとかショタですとかを 書いています。

スーパーダブルはエッチ系ではないけれど、 やおい系であることは否定できない・・(^^;) でも星野さんの絵って猫は独特の雰囲気があって 病み付きになります。

それにしてもダイヤがかわいすぎ・・・。 男の子萌えな方にオススメです。

らいかデイズ
らいかデイズ
らいかデイズ

4コママンガ。猫は萌えの神髄とはコレだと思うのです。 こびすぎたのは萌えじゃないにゃ〜〜っ! (心の叫び)

なんでもそつ無くこなせる(でも恋バナだけは苦手な) 天才少女 春菜来華ちゃんの日常がはにゃ〜な感じです。 ライバル心と恋心を燃やす男の子竹田くんを思わず応援してしまう猫なのです。 が、がんばってっ

ほのぼのと良いマンガです。

白のふわふわ / スミレステッチ
白のふわふわ / スミレステッチ
白のふわふわ / スミレステッチ

萌えといったら外せませんの山名沢湖さん。 ふわふわとした絵柄と絵本や童話のようなお話がとても魅力です。 猫はとてもファンなのです。 (コミケで同人誌も買ってます。)

「話・絵 = 山名沢湖」というところと、 あとがきが一つのマンガ(エッセイじゃなくてちゃんとしたショートショート)なのが 彼女(だとおもうけど)らしくておもわずニンマリしてしまいます。

とても、とてもオススメです。とりあえず買おいましょ♪ 直ぐ買いましょ♪ 今買いましょ♪ (委員長お手をどうぞ、もオススメです。いちご実験室は初期作品でちょっと微妙(好きだけど)。)

30Girl.com
30Girl.com
サーティーガール.コム

まず Webで読みましょう! 気に入ったら買いましょう! でんこちゃん系の企業CMキャラクタなのですが、Webサイトでマンガを連載しています。 それ自体は「へぇ〜」程度なのですが、 マンガの内容がなんともバイオレンスなもので・・・。 いいの!?、日立さん!!

実はこの人のショタマンガも好きなんです。 (またショタか・・と言わないでください) あ、このマンガは至って健全なギャグマンガですよ〜。

ちなみに猫のPCの壁紙はココのジョーズ(という名の猫)なんです。

トラギ付録マイコンと評価ボード(自作)

なんだかとてもアセンブラが書きたい気分になったので トラ技の付録マイコンを使ってみようと 評価ボードを作ってみました。

トラギ付録マイコンと評価ボード
トラギ付録マイコンと評価ボード

とは言っても猫はすごいブキッチョなので、 自ら半田ごてを握るようなギャンブラーなことはせず、 元I-Oデータ機器修理部門の半田づけ達人のお友達に 休日返上でニッコリお願いいたしました。

・・・バチがあたったのか動きません・・・。

orz

スピーカとか、基板とか、HHK Liteとか、 なんだかお金ばかり出ていって何も残らなかったのが多かったです。 先月あれだけ散在しておいて、あたしはいったい何をやっているのでしょう。

こうして、悲しい借金ばかり積み重なっていく・・。鬱にゃ。

・・・・・orz

|++ month top ++|

03月17日(木)

ハッカーとそうでないプログラマの違いは プログラミング言語を確かに「言葉」だと捕らえられているかだとおもいます。

可読性とパワー

ハッカーはソースコードの可読性とパワーにこだわります。 多くのプログラマが誤解していることですが、 プログラミング言語で書かれたソースコードは人間が読むものです。

可読性

プログラミング言語を覚えることで あたしたちは機械と会話する能力を得ることができるようになります。[1] しかし、機械が読めるだけのプログラムを作って、 人間が読むことが困難であるもの――長すぎたり、見た目のネストが深すぎたり、 抽象化が成されてなかったり、というプログラムが平気で作られています。

「可読性の高いコード」とは、正しさが容易に理解できるコードのことです。 つまり、間違いが書いてあったときにそれが間違いだと「するっと」理解できると言うことです。

「読みやすい」ということが、プログラミングにおいて計り知れないパワーを持つことを 多くの方は気が付いていません。それを知っているのはハッカーとそれに連なる人々であり、 故にハッカーは優れたプログラムを書くことが出来るのです。

規模との戦い

では、可読性のよいプログラムを書くためには何を気をつけたらよいのでしょうか。

具体的なテクニックは良いコードをたくさん読んでそれをまねすることが 一番の近道なのですが、 心構えとしては「よりシンプルに、適度に短く」[2] です。 というのも、人の理解力は「大規模」に対して非常に脆弱だからです。

人間は本当に大規模なものの取り扱いが苦手です。 大規模であるだけで、簡単な問題であっても人間は容易に理解することが不可能になってしまいます。[3] 2桁の足し算の間違いを人は人目で気付けるけれども、100桁の足し算の間違いを 人は容易に気が付くことが出来ません。 同様に個々の要素がどんなに簡単な手続きであっても、文の長さが長いだけで、 それが一体なにを示していて、しかも間違いがないのかを見極めることがとても難しくなります。

しかしプログラムは年々大規模化していきます。 では「プログラマ」とか「ハッカー」になれば、 そんな大規模なモノをスルッと理解できるようになるのかというと もちろんそんなことは有りません。[4].

そもそもプログラムがいくら大規模になったとはいえ、 現実世界の大規模さの前にはささいなモノ、それでも人は現実世界で生きていけるのですから、 「プログラムの大規模さ」くらいなんてこと無いはずです。

逆にヒトが現実の大規模さを乗り越えるときにつかうノウハウを利用すれば、 大規模なプログラムも十分人間の管理能力の下に置くことが出来ます。 そういう発想の元作られたのが構造化プログラミングやオブジェクト指向プログラミングです。

抽象化

人間が大規模なもの認識するときに用いる武器、それは抽象化です。

抽象化というと「曖昧に考えること」と思われがちですが、それは間違った認識です。 抽象化とは物事の本質のみを抽出することです。[5] 本質を取り出しディテールを隠蔽すれば、大規模なものであろうと 人間の管理能力下に収めることが出来ます。

構造化プログラミングでは関数を、オブジェクト指向プログラミングでは オブジェクトを使います。

たとえば、「ダイアログを開く」という関数は、 ウインドウハンドラの取得や、イベントループの始動、画面のレンダリングなどを 隠蔽しているはずです。 ウインドウハンドラを取得したり、ループを開始したりなどという処理は、 「ダイアログを開く」という本質に対する手段にすぎません。

また、「ダイアログを開く」という行為そのものも たとえば「住所を入力する」という処理の、最終確認("更新します、よろしいですか?"等)の 手段であるかもしれません。

こうして十分に抽象化していけば、 見た目の規模は小さいものになります。

構造化プログラミングは上記で例示した「段階的詳細化」を抽象化の主軸としています。 オブジェクト指向プログラミングは「分類化」を抽象化の主軸とします。[6]

どちらもプログラミングと関係なしに人間が使ってきた抽象化の仕組みで、 これらを導入すると ソースコードが読みやすくなる為、 正しく動くことを容易に理解できるようになり、良いプログラムを作ることができるようになるのです。

常に「今ズラズラっと書いているコード群って本質的に言うとなんなんだろう」と 意識しながらプログラミングすること、それが上達へつながります。

[1] 多くの人は「会話する」ではなくて「命令する」だと思っているのかもしれません。 でも、「会話する」と「命令する」は大きく違います。 コミニュケーションが双方向かそうでないかという根本的な認識の差があるからです。

[2] 隙間や行間を詰めろという意味でないのに注意。(それは手段と目的を取り違えた愚かな行為です) ハッカーの ポール・グレアムさんは「短い」ということは トークンの数が少ないと言う風に解釈するのがより適当だと言っていますが、 猫もそう思います。

[3] 良いプログラムを作る手法の戦いは、この大規模を扱えない人間の脳との戦いでもあります。 そこから「構造化プログラミング」「文芸的プログラミング」「オブジェクト指向プログラミング」などが 生まれていきました。

[4] 実は自分の脳をコンピュータライズしてしまった人たちはこの業界では意外に多いです。 (本物のプログラマを参照のこと) しかし「ヒトの脳」というハードウェアの非効率な使い方です。 そういう脳の使い方は美しくないし、究極的には不利です。

重ねて言いますが、そういう人達は既に「人類」では無いことに注意。(ボーグに近いかも(笑) )

[5] 抽象化によってディテールを隠蔽することは、 ディテールの層からの視点でみれば分割することに他なりません。 ただし、ディテールの「分割と隠蔽」であって「除去で」はないことに注意。 結局は扱う情報量は変えられないので、上手な分割によって 見かけの量を減らす行為が「抽象化」です。

(ディテールを除去してしまったパワーポイント語は 確かに理解しやすいけど、 それが打倒かどうかを判断する要素が掛けてしまい、 それ自身では正しさを理解することが出来無くなってしまってます。)

[6] 正確には違います。オブジェクト指向では分類と集約を主な抽象化ベクトルとします。

ヒトは意味を持った分割を行い、その単位内に含まれる事象のシンプルな代替表現を作り出すことを 得意とする。その場合、表現系としてはたいてい階層表現になる。

構造化プログラミングでは、主に手続きの階層化を行うが、 オブジェクト指向プログラミングでは手続きとデータを同時に階層化する。 オブジェクト指向における抽象化は

食べ物
 ├ 果物
     ├ リンゴ

と言った分類(汎化-特化の関係)

車
 ├ シャーシ
 ├ ボディ
 ├ 車輪
      ├ホイール
      ├シャフト
      ├タイヤ

と言った集約(全体-部分)の二つで構成されることが多いです。

言語のパワー

たとえば、以下のx86用アセンブラのソースコード[7]

MOV AL ,1
ADD AL ,2
MOV DL ,3
SUB DL ,1
MUL DL

が、何をしているか一目でわかるでしょうか。 これは 一般的な数式(中置記法)をで書くと、

(1+2)×(3-1)

のことです。 この場合、アセンブラよりも 算術記法のほうが 同じ内容をより簡潔に記述できる、 ということになります。 同じ内容をより簡潔に記述できることを「パワーがある」と言います。

言い方を変えれば、言語の抽象化能力が上がれば上がるほどパワーが上がります。 LispはFortranの次に古い言語ですが、 未だに最強であるのは、その設計が数学的であり 非常に抽象化能力が高いからです。

抽象度のパワー

抽象度が高いと何が良いかというと、 高い抽象度は、一度により多くのことをシンプルに扱うことが 出来るようになることです。

人間は一度に7つくらいことしか一時記憶できない仕組みの脳を持っています。 但し箱の中身の種類は問わないアーキテクチャなのがミソです。

たとえば電話番号を覚えるとき、 単純に数値の並びを覚えようとすると、7桁以上になるととたんにつらくなります。 この状態で複数の電話番号を暗記しておこうとしても 覚えてられる可能性はとても低いです。

しかし、語呂合わせなどで覚えるとこの限界は簡単に突破されます。 これは電話番号を構成する数値一つ一つを箱に一個づつ詰めていくか、 電話番号を一つのフレーズに変換して、そのフレーズを一つの箱に詰めていくか ということです。 人間の脳のボトルネックは一時記憶の数なので、 変換というコストを払ってもシステム性能は却って向上するのです。[8]

こういう脳の持ち主ですから、人間は抽象化―― つまり複雑な物事の系から「本質」と取り出して、 グループの外側から見ると一つのオブジェクトにしてしまう ことを得意とします。

つまり抽象化能力の高い言語をつかうとパワフルになるのは その言語をつかう人間です。 人間のために言語は進化してきたのであって、 コンピュータにとっては「記憶」がボトルネックにならないので 抽象化能力は必要ない、つまり言語の進化は全然関係ないのです。

このことから、プログラミング言語の優劣は、 「人間の脳」というアーキテクチャへの最適化度に寄ることが理解できるとおもいます。 つまりは、「可読性 (←人間が読みやすいと感じること)」 と、「抽象化 (←人間の脳のボトルネックをいかに押さえるか)」こそが、 言語の優劣である、と言って良いと思います。

抽象度が高すぎるとつらい?

しかし人間は全く新しい抽象概念を足場に思考を組み立てるのを 簡単に習得できるようにはなりません。 とくに長く生きた人は「こういうモノの見方」というので 脳こり固まってしまい、日常よりも抽象度が高すぎると それを操れなくなってくるのです。

たとえば、「時間」と「分岐」という考え方のほうが 「集合」よりも考えやすいですが、「集合」の方がよりパワフルです。

ソースコードの記述と実行は(対話型インターフェイスでないかぎり)時間同期を必要としません。 つまり、ソースコード中に処理記述が時系列にならぶ必要はないのですが、 現状のプログラム言語の多くは処理記述を時系列にならべる「手続き型」が大人気です。

手続き型はすでに時代遅れなメタファだと思うのですが、 未だに「コンピュータにやって欲しいことの手順を書いて、命令する」というメタファが コンピュータという概念に染み渡ってしまっているからだと思います。[9]

また、現在の環境(≒世間)では、 最初にプログラムに触れるときに「プログラムとはそういうモノだ」という教育をされてしまうので、 多くのプログラマの脳は1960年代の最新テクノロジで今もフォーマットされ続けているのも 大きいでしょうか。[10]

こういうのに対しLispのように徹底的にけんかを売ったり、 Smalltalkの要に「手続きよりよりなじみやすいですよ」と誘ったりする言語もあるのですが、 今のところ人々の脳にパラダイムシフトを起こすのに成功した実績はありません。

結局、「関数のコール・リターン」というメタファを捨て、 メッセージ送信とそれに対する責務の実行という(人の本質にとってより解りやすい)新概念であった OOは、手続きとコール・リターンに飲み込まれてしまいました。しくしく。[11]

結局のところ、その時代の人々の脳の平均フォーマットに迎合した言語が 強いです。

Pythonは可読性が高いと評価されていて、合理的かつ意外性のない文法と、 適度なパワーが魅力です。 反面 無名関数[12]や式と文の区別[13]に難があり、 十分にパワフルかというと、ほんの少しの疑問があるのも確かです。 (ポール・グレアムさんの受け売りですけど)

[7] このアセンブラコードは Windowsのコマンドプロンプトで DEBUGコマンドを使えば実行出来ます。

>DEBUG

-A 100
354A:0100 MOV AL ,1
354A:0102 ADD AL ,2
354A:0104 MOV DL ,3
354A:0106 SUB DL ,1
354A:0109 MUL DL
354A:010B 
-g =100 10B

AX=0006  BX=0002  CX=0000  DX=0002  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=354A  ES=354A  SS=354A  CS=354A  IP=010B   NV UP EI PL NZ NA PO NC
354A:010B 01F7          ADD     DI,SI

強調表示部分が入力するところ。AXレジスタに結果「0006」が入っていることに注目。

簡単に説明すると、AL,DLはレジスタ名、 MOVはデータの移動(右のデータを左の場所に入れる)、 ADDは加算(二つの示すモノを足して、左側の場所に結果を入れる)、 SUBは減算(加算と同様)、MULは乗算(ALレジスタと、してされたモノをかけ算し、AXレジスタに格納)です。

ちなみに猫はもうアセンブル言語をしっかり忘れてしまっているので(^^;)、 このコードサンプルはWisdomSoftさんち 持ってきたものです。

[8] そろばんが好例です。 そろばんは「計算する」というタスクのうち一時記憶のみを移譲するデバイスです。 (つまりそろばんは人間用拡張メモリです。)

「そろばんを弾く」という作業は、脳内のアクセスよりもずっとずっと遅いのですが、 これだけの遅さであっても人間の計算能力を飛躍的に高めてくれます。

いかに「一時記憶の個数」が人間の脳にとって致命的なボトルネックかを 示していると思います。

[9] 手続きメタファはシングルタスク & 一極集中的です。現在の分散に向かうアーキテクチャには 余り向いてませんので、そろそろ何とかしないと・・。

並列プログラミングや Webサーバ / クライアント間の シーケンス分割が難しいのは、 そういうのに適さないメタファで強引に推し進めているからだと猫は思います。 (「継続」とか使えば簡単なのに・・・。)

[10] 「プログラム」の語源自体が手続きメタファですから・・・。

[11] これは誰がなんと言おうとC++の罪なのですが、 ストラウストラップ博士が愚かだったかというとそうではなく 逆に賢こすぎのせいかなぁと思います。

と、いうのもメッセージ送信メタファが実現するモノの本質に 「メッセージ」という概念が必要ないことに気が付いて、 オブジェクト指向の概念を一般かしちゃったからです。

オブジェクト指向も従来のコール・リターンモデルも手続きモデルも 一つの「手続き」というルールの中に再構築してしまったからです。 結果「オブジェクト指向」を言語パラダイムから設計パラダイムに一段押し上げてしまった、というわけです。 (「手続き型」「関数型」「論理型」というプログラミング言語のパラダイムに Smalltalkに合致するものはない。・・・と猫は思う(要調査です) )

しかし「メタファは脳内で好きなように再現してください、 そうすれば好きな方式でプログラムを書けます」的な言語で 「オブジェクト指向を学んでください」というのは非常に酷な話です。 これは言語設計者の見ているユーザが、「プログラムを知らない人」か「技術者」かという ところに起因する問題なのかなぁ、と思っています。

[12] 無名関数という言い方よりは「関数リテラル」というほうが良いかしら。 「処理」も「状態」も本質的には同じモノなので、

hoge = 1;           // 1 は数値リテラル

や、

hoge = "abc";       // "abc" は文字列リテラル

のように書けるならば、関数も同様に

hoge = ( x, y ){
                    buf = x + y;
                    print( "値は%dです" ,buf);
                    return( buf );
               };

のように書けるべきです。(この時 変数hogeに束縛されるのは returnされたbuf値ではなく、{ ... } そのものです。)

これを無名関数といい、歴史的経緯から「lambda」というキーワードを 使うことが多いです。

[13] 本質的に文と式を区別する必要は有りません。けれどこの区別は 一部の人に心地よいようです。

式とは「評価されると値を返す」もので、 文とは「評価されても値を返さない」ものです。

具体例を示すと、C言語の 「hoge += 1」は式なので、

while( 1 ){
    printf( "現在の値は %d です" , (hoge += 1) );
}

のようなことが出来ますが、Pythonの 「hoge += 1」は文なので、

while True:
    print "現在の値は %d です" % (hoge += 1)

は出来ません。(「hoge += 1」が値を返さないからです。)

似たような区別に古典的言語であった 「値を返すコードブロック→関数」「値を返さないコードブロック→プロシージャ」と がありましたが、現在ではそういう言語は無くなってきています。

ちなみにあたしたちが日常で使っている自然言語の「文」は 「○○して、××」のような連結が出来、多分に式的です。

|++ month top ++|

03月16日(水)

先月は精神的に参ってましたけれど、 ようやく復活してきたようです。

猫の復活度合いは書欲の復活に現れます。 書きたい気持ちでいっぱいになれば絶好調です。

で、今月の猫日誌を見て頂ければ解ると思いますが、 書きたい意欲が復活して参りました。 ようやく「アレも書きたい、コレも書きたい、でも時間がな〜い!!」という 状態になってきたので、猫としては絶好調です。

そんな脳みそくるくる空回りだと、 いろんな風に思考が飛び火するもんです。ええ、下らないダジャレからでも コラムが一本掛けてしまう。うーん恐るべし、あたし。

今回猫の頭で付いちゃった電球は「七難ハック」でした。

七難ハック

ゴロの良さとへんなオーバーラップでこの言葉を思いついたときは 我ながら「おお〜っ」と思いました。タイトル先行ネタです。

ハッカーについては世間の誤解も大きいのですが、 猫としては 善悪とは切り離して純粋なコンピュータに対する知的好奇心の あふれ出る状態を指すような気がします。

ハックの定義として猫は「手段が目的である」を挙げたいと思います。

ハックしたい、という衝動のために手頃な目的を探してくるのがハッカーです。 ハックしたいが為に難題を追い求めるのがハッカーなので、 まさに「我に七難八苦を与えたまえ」、というわけです。 でも、「難」を「苦しい」とは思わない(むしろ愉しい)のがハッカーでので、 「八苦」ではなく「ハック」なのです。

クラックを目的として腕をふるう人たちとか また、クラックする腕がないからツールや既製スクリプトを使い回す 自己顕示欲やビジネスの奴隷さんたちは 既にハッカー的ではないわけです。

ハッカーはハッカーとして生きるだけで先進的なノウハウがストアされていきますので、 時間制約の緩い(つまり家に帰ってからハックする暇のある)勤務体系で、 努力評価ではなく実力評価な会社をつくれば技術てきに凄くなると 猫はのほほんと思います。

あ、ちなみに実力評価主義が崩壊しているように感じるのは 猫はそれが「実力」ではなく「実績」評価にすり替わって運営されているからだと 根拠もなく思っています。

ああ、ハックの時間が欲しいわぁ・・・・。

|++ month top ++|

03月15日(火)

最近お気に入りのマンガがあります。 30girl.comという漫画で、 Webコミックです。

とても面白いので猫のパソコンの壁紙は 全部このマンガの「ジョーズ」(という名前のしゃべる猫)に なっています。

だっておもしろいんだも〜ん♪

30girl.com のスゝメ

このマンガは 日立空調システムの企業キャラクタの漫画ですが、 漫画自体はもう日立の陰も形もありません。(笑)

岩崎つばささんはショタ畑の漫画家で、猫はひいきにしていたのですが、 こんな漫画を書いているなんて最近まで知りませんでした。 やるにゃあ。

猫はとても面白いとおもうので 去年でた単行本を買ったのですが、 あれ・・・なんだか面白くない。Amazonの評価もあまり思わしくないです。 なぜなぜ?

Webの「間」

じつはこの漫画が面白いのはWebの読込という「間」と 時々行われるハイパーリンクを駆使したマルチビュー的展開、 そして紙と違い面積がコストに直結しないWebの特徴を生かした スペースという意味の「間」、 これを上手につかって笑いを構築しているからです。

30girl.comは1ページが基本的に四コマで構成されていて、 次の四コマが見えないため、小さな起承転結がそこにはあります。 また、次の四コマの場面展開の間に笑いがあるわけで、 まさに絶妙と言った感じ。

全話の定型フォーマットとして、 最後のオチに行く前に 30girl.comのロゴだけのページが 挟まります。 で、その次のページは1コマだけオチのコマがあるんですが、 これはWebの読込時間を利用した間の演出として見事です。

30girl.comでやっていることは、要は紙コミックでもある改ページ効果のWebへの応用です。

Webの「読込時間」という 通常のコミック組み立て方法では邪魔者だったものを 見事に構成に利用したのがこのコミックの素晴らしいところ。 「やるにゃ 岩崎つばささん、やるにゃロンドベル!」です。

紙への移植

残念なことに単行本では、 1ページに4コマ2本を詰め込み見開き4本も目に入ってしまう 単行本ではそのおもしろさが激減してしまうのです。

4コマずつに挟まれた間は消え去り、ストリーム的に読んでしまうため 読込時間の間の思考のオーバーラン「次はどんなのかなぁ」が無いため、 場の転換のおもしろさが感じられないのです。

また、40girls.comではハイパーリンクをつかって キャラクターのモノローグなどを小コマでポップアップさせているのですが、 これをうまく紙媒体に紙展開する方法はないのじゃないかしら。

猫はこの漫画を単行本にするなら、1ページ1本で、 中央に置く、という方法が必要だと思います。 かなり構成に気を遣って間をデザインして やっとWebの8割くらいのおもしろさを再現できるかしら。

つまりは、Webコミックの場合単行本化は再録ではなく移植なんです。

そして文化は巡り巡る

メディアが変われば 漫画も変わるってのを ひしひしと感じました。と、いうわけでWeb発のはWebで読むのがやっぱりオススメ、 いつまでも置いておいてくれないのが悲しいのですが、読めるうちに是非♪

> 30girl.com

|++ month top ++|

03月13日(日)

今回は三猫名義じゃない文章で書き始めたモノですが、 猫日誌に使うことにしました。

最初はいつものデスマス調に直そうとおもったのだけれど、 文章との整合性がとれない感じで、思いとどまりました。 (内容が毒々しいのでデスマス調にしてしまうと 壮絶な嫌みのようなフレーバーを醸し出してしまうのです。(笑))

猫は批判・批評が得意じゃないです。 感情がにじみ出て、批判ではなく攻撃になってしまいます。 今回も結局「人格攻撃」に行き着くわけで、 これは不毛な否定でです。

そんな猫が書いた「批判」だから、とても不快な文章だと思います。 それでも、そういうのを乗せてしまいたいという誘惑があるあたり 猫のどうしようもなさをしみじみ感じてしまうのです。


岩谷宏氏はコンピュータ関連の翻訳家であり テクニカルライターだが 批判が多い。なかには名指しでバカという同業者までいる。

彼の訳は崩壊しているのか? 技術記事には間違いが多いのか?

そうではない。 しかし彼の理論は「決めつけ」が多く差別的である。 ようするに、結論と自身の正しさの主張のために理論を組み立てる。 そして彼の訳は他人の著作物に「訳注」と称し 持論をちりばめていく。読んでいて不快この上ない。

彼の訳の問題については岩谷 宏は訳注付けるな!に詳しい。

岩谷宏氏批判

先日「C++の設計と進化」を購入したが、これの訳者が岩谷宏氏であった。 この件については Maz日記で 本著の購入を氏が訳というだけで躊躇されていたから、 影響を受けやすい私は「えっ、氏ってそんなに惨いの?」と 思ってしまった。

そういう風に改めて読んでみると。 気にしなければ気にならないけれど気にし出すと止まらないようなのを 見つけてしまった。 その一つをあげよう。

それは、12.8で「純粋仮想関数」へ

この概念のセマンティクスはシンプルで、実装も簡単だ。 問題は良いシンタクスを見つけることだ。次のような案がある :
class LotterySimulation
    :public Lottery ,public GrapicalObject {
    // ...
    virtual int l_draw() = Lottery::draw;
    virtual int go_draw() = GraphicalObject::draw;
};
これは純粋仮想関数(訳注2) のシンタクスの、無理のない拡張と言えるだろう。

という本文に対し、

訳注2:pure virtual function,ベースクラスにおいて実装のない仮想関数。 Javaの抽象メソッドに相当。 virtual T func() = 0;という書き方(=0;がミソ)をすると、func()はTタイプの オブジェクトを返す純粋仮想関数である。純粋仮想関数のあるクラスを"抽象クラス"という。

という訳注がある。 しかし、実は純粋仮想関数には 13.2 抽象クラス(の13.2.1)で本文中に説明があるし、 そもそもこの項は純粋仮想関数について述べる項とは違う。

過大は親切心と受け取ったとしても腑に落ちない点がある。

  • 英語を記す意味がわからない。純粋仮想関数とpure virtual functionの間に訳注をいれるほどの相互連想性が無いとはとうてい思えない。
  • Javaを引き合いに出す意味がわからない
  • 原著で説明箇所があるのに(その参照を示さず)なぜ訳者が説明を行うかが不明である。
  • 抽象クラスの理解がこの本文にまったく必要ない。蛇足だ。

この説明は読者をバカにしているとおもう。 C++を知らない人間が読んでいるという偏見を感じる。 また、ストラウストラップに対する侮蔑も感じる。 「ここで説明しないのはヌケてるなぁ、よっしゃ、オレ様が説明しておいてあげよう」と。 これは原著者の「読者はC++についてそれくらいは知っておろう」というスタンスに対する 訳者のクーデターだ。 事実、0章では「本書はC++のユーザ、つまりプログラマやアプリケーション設計者が読むための本として書いた」とある。 (訳者が著者から著作を奪い取ってどするというのだ!)

つまるところここには訳注をつける合理的理由は無い。 仮につけるとしても、

訳注2:純粋仮想関数のシンタクスは virtual T func() = 0;である。 (純粋仮想関数については13.2.1を参照せよ)

で十分ではないか。 本文ではリネーム構文案が純粋仮想関数のシンタクスの 無理のない拡張であると述べているだけだ。 セマンティクスの理解は(ここでは)必要ない。

そして仮にこのような注だとしても、これは断じて「訳」注ではない。

自己顕示欲ではないか、という仮説。

他の章で解説のある純粋仮想関数へのセマンティクスを シンタクスを問題にする局面で注釈を入れる意味が私にはわからない。

この問題をもう少しほじくり返すと、訳者が訳注をつける「合理的な」一貫性がないということだ。 例えば、岩谷氏は純粋仮想関数を「読者が解らないと思って」訳注をつける「親切な」訳者だと仮定しよう。 (しかし、ありがた迷惑でしかないと私は思う)

親切な訳者はJavaの相当機能で置き換えて説明したり、 よりポピュラーな"pure virtual function"という言葉で理解を促すわけだ。 (しかしpure virtual...のほうがポピュラーという事実はない)

岩谷氏の想定読者は「C++をよく知らない」「Javaならわかる」 開発者であると思われる。 ならば入れるべき所は他にもあろう。注釈を入れる箇所にも注釈のない様にも 不可解千万である。

氏の訳注には一つの仮説を立てれば整合性が整う。 「自己顕示欲のために行っている」と。

氏があらゆるところで批判されるのはこれだ。 しばしば訳注を入れる動機として 読者のためではなく、自身の自己顕示欲のために行っている。 (すくなくとも私にはそのようには見える) 「彼はきっと"凄い"と言って欲しい人で、 凄いと言ってもらうことを目的としている。」と言う風な解釈に 説得力を持たせる言動を氏は慎まない。 他人の著作物を土足で踏み荒らすことを厭わない。モラルが無いのだ。

もう一つ、氏の言動に常に他人を見下す臭いがするのも 嫌われる原因だとおもう。 しばしば、氏は「劣った人間」というレッテルを貼り 論理にならない論理を組み立てることがある。(参考)

私は思う。「C++の設計と進化」などという本を読もうとする人間が C++を解さないと考えてしまうこと自体が異常ではないか。 自分がC++の出来る凄い人だから、一般の読者は解らないに違いない。 Javaなぞをたしなんで満足しているのだろう?という傲慢を感じる。

望めば望むほど手に入りにくくなるモノ

こう書くと、なるほど岩谷宏はどうしようもない人間でなのだなぁという 印象を受ける。 確かにどうしようもない一面があるのは事実ではないか、と 私はおもう。

しかし、本当にどうしようもないかというと、それはどうだろう。翻訳のスキルを持ち、 プログラミングにも造詣を持つ彼が凄くないなんてことはない。 客観的に見て私よりずっと凄い人だとおもう。

だが、彼は己を知らない。己の知っていることが真理だと思っている。 誰かが誰かのスーパーセットであるなんてことは 相当の差がなければあり得ないのに、彼の中はカースト制度で構成されて、 劣る人間は全てに置いて劣るという訳の解らない世界観で支配されている。 ――という印象を私は受ける。そういう岩谷像を描くのを私は禁じ得ない。

ビャーネ・ストラウストラップ氏はとても優れた人間だ。 しかし、そんな彼でも自身が「こう」感じているから「こう」が正しいと 判断するのは危険だ、という姿勢でC++の設計に望んでいるのが 本書を読むと随所に見える。 C++の言語的混乱をみるとそれが正しかったかどうかは微妙だけれど、 それは賢い物の見方だと私は思う。

自身の正しさを常に疑うことは賢い。 しかし自身の正しさを自身で検証する術はない。 バグのあるテストツールでツール自身のテストをしても、 どちらのバグだかわからないし、そもそも検出出来るかも解らない。 それに気が付かず、「自身は常に正しさを己に問うておる。 だからかなり正しいハズだ」と思い、 自身の論を一般普遍の論または真理に近いモノと自負してしまう。 ありがちなだけに悲しい。

自身の判断を真理だと思いこむ訳者と、 自身の判断の正しさは自身では検証できないということを 肝に銘じている原著者の組合せは、 この上ない皮肉である。

岩谷氏の自己肥大は止まらないが、 尊敬とは望めば望むほど手に入らないものだ。 自らを過大評価すれば、そのぶんまわりからは過小評価を受ける。 世の中上手くできているものだと感にいる。

あたしのこと

と、言うわけでかなりの毒批評でした。 もうちょっと建設的なものが書けるようになりたい。 (こんなふうに)

結局は「著書から想像された岩谷」さんへの個人攻撃文章です。 ホントの本人像と一致しているかどうかなんて解らないのに、 それを「人格悪い」と言ってのける批評は卑怯です。

猫は、 「あ〜あ、この人って『オレって凄いんだぞ』病を直せば 素直に(相応な)尊敬をもらえる人なのに、残念。」というのと、 「訳って『この訳ダメだからあたしが訳す!』すると著作権法違反になってしまうので 訳者さんの責任というのは重いのです。」の両方の思いで文章を書いたのですが、 どうしてこう嫌みっぽい文章になってしまうのでしょう。反省・・。

ちなみに猫も「あたしって凄いでしょ、あなた達っで愚民でしょう」病の患者です。 自覚はしていて、気をつけているつもりなのですが やっぱりダメです。この病気の患者はロクデナシばかりです。猫はダメ猫です。

岩谷さんには HGUCやMGカトキハジメさんのMSリファイン(Zを除く)を 見習って欲しいです。 オリジナルを尊重するということを忘れてはいけないと思うのです。 自分が改善だとおもっても、他の人から見れば冒涜・破壊行為でしかないのですから。

ああ、柳澤氏のMGガンダムデザインは10年たった今でも許せないっ!!

|++ month top ++|

03月12日(土)

もう春です。4月になればういういしい新人さんも入ってきます。 ああああ、新人ですよ。

今年の猫は「先生」です。 新人さんへの講師をやることになっているのですが、 私に割り当てられたお題は「オブジェクト指向の概要」。・・・・・・また難しいものを(TT)

オブジェクト指向とは何?と聞かれたら、猫は答えに詰まってしまいます。 嘘は教えられるけど、本当のことは教えられないからです。 なぜなら、オブジェクト指向の定義はない からです。(ホントよ、信じて・・)

ふたつのオブジェクト指向

世の中これだけ「オブジェクト指向」「オブジェクト指向」ともてはやされているのに、 その定義がないなんてにわかに信じられないかもしれません。 辞書を引けばそれらしいこと書いてあるじゃない、とか思うでしょう。 でも、OOをちょっと探っていくだけで直面します。ホントに、ホントに、定義が無いのです。 深く潜っていくとなぜか底が全然違う2箇所に割れていってしまい、 どちらが本当のオブジェクト指向なんだか、誰にも解らなくなってしまうのです。

なぜこんなことになってしまったかは、歴史を追ってみるのが一番です。 一番最初のオブジェクト指向言語に逆戻ってみることにします、 ・・・って、アレ。これも諸説ふんぷんで二つある・・。(TT)

Simla、後ろ、後ろっ

世界初のオブジェクト指向言語。 一つは「オブジェクト指向」という言葉を作った[1]Smalltalk、 もう一つはクラスやオブジェクトを最初に実装したSimulaです。 まずはより古いSimulaの方から追ってみましょう。

Simulaは元々「Simulation language」の略[2]、つまりシミュレーション用に開発された言語です。 多くのモノをシミュレーションするようなプログラムでは従来の コードとデータが分離していては、常に「アクセスする情報」と 「アクセスする方法」を使う側がセットで使って上げなくてはならなくて 扱うのが面倒くさいです。 だから、「振る舞いを持つ状態」である「オブジェクト」と それの型を定義する「クラス」が実装されました。

このSimulaの「オブジェクト」と「クラス」は魅力的な概念で、 二つの言語に影響を与えました。 SmalltalkとC++です。

おしゃべり言語

Simuraにインスピレーションを受け、 オブジェクトとオブジェクトがメッセージを送信しあって 相互作用を起こすプログラミングモデルを実装してみたのが Smalltalkです。

Smalltalkの開発者 アラン・ケイさんはこう考えました。 「オブジェクトに対してメッセージを送る。 そうするとオブジェクトはそのメッセージを実行する。」 こういうシンプルな仕組みだけでプログラムが書ければ、 コンピュータはもっと人間に解りやすくなるんじゃないかしら♪

そして実装されたSmalltalkは、これまでの手続き型言語とは 一風変わった文法を持つようになりました。 Smalltalkの文法には「文」がありません。 Smalltalkは「メッセージ式」という「式」を用います。

メッセージ式は オブジェクトがオブジェクトに対してメッセージを送ることを 記述する式です。 メッセージを送られたオブジェクトは 自身に定義された メッセージを遂行するためのメソッド(= 手法の意)を起動します。

こんな風にSmalltalkはメッセージというメタファ(比喩)を持ち込み、 「世界をオブジェクトの相互作用で描く」という人間の認識に近いパラダイムで プログラムを記述出来るようにしました。 これを「オブジェクト指向」と名付けたのです。

[1] Smalltalkとは「おしゃべり」という意味なんです。

クラス付きのC

C++ もまたSIMURAに影響を受けた言語です。 Cに「クラス」があればどんなに便利だろう、という実用本位の発想からうまれた C++は 抽象データ型 を自在に記述できるCとして産声を上げました。

実はCを含めこのころの言語は「型」の概念の実装が右往左往している次期でした。 型はあまり固くしすぎるととてもプログラミングの効率が悪くなりますし、 緩くしすぎると、実行時にしかチェック出来なくなります。 C言語は値に型がなく、その値を格納する変数に型があります。[2] これはそこそこ上手いやり方なのですが、データに適さないやり方で扱うと すわバグになります。

本当はデータにはデータに適した扱い方があってそれ以外の方法でデータ自身に触れられない、 というのが理想です。 しかし型変換のできない言語は著しくパワーに欠けます。 だから変換しても安全な型への変換はできる、 贅沢を言えば安全でない型変換はブロックできると素晴らしいです。[3]

と、これって「クラス」と「オブジェクト」そのものじゃないですか。 そう、C++は「オブジェクト指向のC」じゃなくて、 「クラス付きのC」なのです。[4]

その証拠に、C++では(Smalltalkを源流とする)オブジェクト指向の重要なメタファである 「フィールド」「メソッド」「メッセージ」と言う表現を嫌います。 C++では「フィールド」を「メンバ変数」、 「メソッド」を「メンバ関数」と言います。 「メッセージ」についてはその概念そのものが排除されました。

C++ でいう Objectとは「振る舞いを持ったデータ」に他なりません。 「状態の管理と保持を束ねたもの」をObjectと呼んだわけですが、 これはSimuraの発想とまったく一緒です。

実はC++はSmalltalkの影響を受けていません。 C++をオブジェクト指向言語というならば、Smalltalkをオブジェクト指向言語のrootに据えることは 実はできないのです。[5] しかし、「オブジェクト指向」と言う言葉を作ったのはSmalltalkです。 うーん、矛盾するわっ・・・。

[2] Cは「キャスト」と言う方法で、強引に変数の型を変更することができます。 これはCをとてもパワフルな言語にしていますが、不具合の源でもあります。 Cの型の考え方は機械語チックです。

[3] ここで上げた「贅沢な型」の条件は、よく言われる言い回しにすると、 「カプセル化」と「継承」、「多態性」 です。 これはC++が定義するオブジェクト指向の必須要件そのものです。

[4] C言語にメッセージ式を追加した言語として「Objective-C」というのがあります。 これはMac OS のネイティブ言語として使われています。 また、C++の初期の言語名は「C with Classes」でした。

[5] C++流の定義でいくと、Simulaもオブジェクト指向の定義に合致します。 なので、「最初のオブジェクト指向言語」というのはSimula説とSmalltalk説に分かれるわけです。

オブジェクト指向の本質は?

例えば、現在「オブジェクト指向とは・・・」とIT系の辞書調べると 必ず

  • カプセル化
  • 継承
  • 多態性

の三条件[6]が必須と説明されます。 ですが実はコレ、C++のオブジェクト指向なんですです。

一方Smalltalkのオブジェクト指向では、 「オブジェクトへのメッセージ送信」というメタファで プログラムを記述します。 このオブジェクト指向では「継承」は必須ではありませんし、 「カプセル化」や「多態性」もあまり重要ではありません。 (勝手についてくるという感じかしら)

Smalltalkプログラムの全てを オブジェクトとそれに対するメッセージ送信で記述するため、 「オブジェクト指向」は新しい機能というよりは 計算モデル[7]に近いです。

Smalltalkにはif-elseのようなフロー制御ステートメントはもとより、 クラスの生成すらスーパークラスへのメッセージ送信で行います。 このメッセージメタファを前面に出したシンタックスは Algol系の文法を持つ言語――PascalやBasic、C と言った言語には とことん馴染みません。

一方、C++の作者 ストラウストラップさんは、 オブジェクト指向を機能的に満たすには 最低限先の3条件を満たせば良くて「メッセージ」は必要無い、と考えました。 「メッセージを受け取ったオブジェクトがそれに対応するメソッドを呼び出す」のと、 「オブジェクトのもつメンバ関数を、外から呼び出す」のとは、 結果的に同じことだからです。

この考え方は構造化プログラミングの時と同じく 既存言語のシンタックスを大きく変えないため、 「Objective ○○」を可能にします。 こうしてオブジェクト指向は Smalltalk定義とC++定義の 元祖・本家に二分派してしまうのでした。

[6] もともとは、「抽象データ型」、「派生」、「仮想関数」と言っていたそうです。 それぞれ「カプセル化」「継承」「多態性」とおなじ意味です。

[7] 計算モデルとは、手続き型、関数型、論理型、と言った言語の分類のことです。 手続き型はフロー制御構文や(if-else、while、gotoなど)を使ってプログラムを 「流れ付きの文」として記述する方法、 関数型はプログラムをネストした(数学的な意味での)関数の固まりと考え、プログラム全体が 「式」で構成されるもの、 論理型はプログラムを命題と述語で記述し、論理式(真・偽、または真・偽・不明)で構成されるものです。 (論理型は説明あってるかしら・・自身ありません)

Smalltalkのメッセージ式で構成されたプログラムは 一応手続き型なのですが(多分..)、メッセージ伝達モデルと言っても良いなぁというくらいには 手続き型とは似てません。

メッセージ指向とクラス指向

このように、Smalltalkの言うオブジェクト指向とC++のいうオブジェクト指向は違うモノです。 ただ、ある程度にているので全然違う話をしていても途中までは話が合ってしまう 妙な関係でもあります。 これらを厳密に分けて考える時、前者をメッセージ指向、後者をクラス指向と言います。

メッセージメタファはとても解りやすくシンプルです。 オブジェクトには (ある関数をメンバに持つ)「型」ではなく、 (あるメッセージを処理出来る)「責任」を果たせれば良いのです。 しかしメッセージメタファは「オブジェクト指向にに必須な何か」の 良くできた比喩ではあるけれど「オブジェクト指向に必須な何か」そのものではありません。

一方抽象データ型のスーパーセットとしてのオブジェクト指向な C++は「責任が果たせること」をクラスという「型」で保証することを 重要に思っています。 メッセージに対してオブジェクトが行うことは十人十色というのが オブジェクト指向の魅力なのですが、 型保証でこれを実現するには 同じ「型」を派生する「継承」とその中での「関数呼び出しに対する 実行内容の十人十色」を実現する「多態性」が必要になるのです。[9]

なるほど、うまいことやってるわぁ、なC++です。 メッセージメタファという上手な比喩が指していた何かを これまた上手に箇条書き要素に分解してしまいました。 なのでC++の(=ストラウスとラップのいう)オブジェクト指向が決定版かと思いきや、 問題をさらに複雑にしているのは、オブジェクト指向にクラスは必須ではないということです。

Simulaにクラスがあったため、Smalltalkにもクラスはありますが、 実はクラスのないオブジェクト指向言語というのはたくさんあります。[10] これらは Smalltalkのメッセージメタファが上手に比喩している「何か」を満たしますが、 C++が上手に箇条書きしたものを満たしません。

[9] この言い回しがピンこないなら、 「カプセル化→抽象データ型」「継承→派生」「多態性→仮想関数」と読み替えてみてください。

C++ がまがい物だといいたい訳ではなくて、 「メッセージメタファ」という大がかりな舞台装置と 実質的に同じコトを こういったチョットしたハックで実現させてしまった 凄さに注目すべきよねぇ、と。

[10] プロトタイプベース オブジェクト指向言語などと呼ばれます。 これらの言語はまず最初に雛形となるオブジェクトを組み立て上げて、 それのクローンを作っていきます。 Selfが有名ですが、もっとも普及しているのはJavascriptです。

これらは カプセル化・継承・多態性に相当するなにかを満たしていますが そのものを満たしているわけではありません。

カレーうどん

Smalltalkは言語と同時にOSでもあった[11]ため、 使い慣れた既存の環境中で実用するプログラムを組むのは難しいことでした。 おまけにガベージコレクタを必要とする動的型付け言語ですので、 当時のマシンでは実行速度が絶望的です。 また「文をフロー制御するモノがプログラム」という重力に魂を引かれてしまった者たちには、 「メッセージ伝達モデル」はあまり評判のよろしいものではありませんでした。[12]

そんなこんなで、オブジェクト指向への実用的なパスとしてC++が受け入れられていくのですが、 これには大きな問題があります。 オブジェクト指向的感覚がなかなか身に付かないのです。

一度メッセージメタファを身につけてしまっているならば クラス指向やクラス指向寄りの言語でも メソッド呼び出しを「メッセージ送信」と脳内補完すればOKですし、 たとえメッセージメタファを知らなくても「オブジェクトとオブジェクトの相互作用で世界を描く」感覚 ――たとえば メソッド呼び出しの「コレやってね。お願い」的ニュアンス[13]が 解っていれば同じことです。

しかし、オブジェクト指向の学習という面では、 メッセージメタファ無しに「オブジェクトとオブジェクトの相互作業で世界を記述する」 オブジェクト指向が解るようになるのは大変です。 そりゃあもう、悟りを開くみたいなモノです。[14]

でも、もともと人間がより簡単にプログラムを組むために生まれてきたオブジェクト指向なのに 悟りを開かなくちゃ開発できないのでは、何かが間違っています。 だからこそ猫はたとえ実務で使わなくともSmalltalkを進めたいな、と考えています。

[11] UNIXなどは全てが「ファイル」で構成されますが、 オブジェクト指向OS としてのSmalltalkは全てがオブジェクトです。

[12] Smalltalk流のメッセージ式とAlgol流フロー制御ステートメントの両方を理解できる ハイブリッドなオブジェクト指向言語というのも作られました。 これの代表は「Objective-C」なのですが、現在の所このアプローチはメインストリームに なることは出来ていません。

[13] 手続き言語の関数パラダイムは「関数を使う」という感覚です。 呼出元、ひいては処理側に主導権があります。 ツール感覚とでも言いましょうか。どこか頭に「実のところコードがインライン展開されるのと一緒でしょう」 という地続き感があると思います。

一方オブジェクト指向ではメソッド呼出はオブジェクトに「これをやってね」という 感覚です。メソッドコールはオブジェクトに処理をさせる「きっかけ」にすぎなくて、 ましてやメソッド中のコードが呼出元に展開されるなんて凄い違和感を感じる・・というのが 「オブジェクト指向的感性」かしら、と猫的には思っています。

この感覚はメッセージメタファを使った場合ピンと来やすいのですが、 この感覚があれば別にメッセージメタファが無くてもまったく問題ありません。

[14] で「オブ脳を作る」などという悲しい錯覚が生まれるのです。 改造人間にならなきゃ出来ないプログラムなんてクズです。

|++ month top ++|

03月11日(金)

Mac mini は理想のコンピュータであって、だから ハッカーがとても好むコンピュータだと思うのです。

ハッカー × マッカー

Mac mini の商品作りのうまさは、 むしろWindows畑のハッカー志願素養のある人こそ 感じることが出来るんじゃないかしら。

平たく言えばここ数年のPC自作のトレンドである 「キューブ」「静音」がどういう母体に成り立っているかが 理解できてるのねぇ、ということです。

応用力(つかいみち)がコンピュータの決め手

現在のコンピュータは汎用的な情報処理機器です。 GUI不要論を唱えるこちらの方は、 Photo Shopを使ったりするようなのは「コンピュータ応用機器」であって 「純粋なコンピュータ」ではないと言っていますが、 応用(=使い道)のないコンピュータなんて、そんなのコンピュータじゃないぞ、と猫は言ってしまいます。

逆になんにでも応用されるからこそ純粋にコンピュータであると言えます。 コンピュータの定義は広く応用出来るです。 応用力のないただの回路をコンピュータとは呼ばないことからもそれは明らかです。 どのような特定分野に深く応用できるからこそ、純粋に情報処理機器であるというのは、 ロードス島戦記の「灰色の魔女」カーラの「絶えず揺れ続ける天秤は中間で釣り合っているのと同じ」論理、 真理です。

・・・と、大きく話が脱線しましたが、 要するに広い汎用性こそコンピュータの純粋性の証。 広く深く応用できればできるほど、より純粋なコンピュータだと思います。 言ってみるなら水中でゴッグに勝てて初めてガンダム というところかしら。(笑)

コンピュータを買うとき、たいていの人はそれを何に応用するかを夢見ます。 それがお金を出すための言い訳だったとしても(笑)、 新しいコンピュータがくれば新しい生活がAdd onされると仮定してみるものでしょう。 逆にコンピュータが買いたくなるためには、 夢を描きやすい姿やバランスが必要です。例えば最近の猫がコンピュータが欲しいなぁ、と思ったとき、

  • CDが部屋にあふれちゃって邪魔だから ジュークボックスPC作ってに入れたいわぁ
  • 一台いいWebサーバーをつくりたいのよねぇ、ZOPEいれてみたいわぁ
  • 会社に自由にできるプロジェクト専用のサーバが欲しいわぁ・・

なぁんてことを考えちゃいます。

専用機器以上の自分の欲しい「ジャスト」を責められるのが 汎用機来るコンピュータの強みですが、 そのためには「物理的な」存在感が重くのしかかる様ではダメなのです。 部屋を専有し、電源を入れたり切ったりをやって上げなければならず、 絶えず轟音を発し、必要以上の経済的負担を強いる機器では、 それはユーザに「計算専用機のためのガマン」を強いることになります。 応用機器として欠陥品ですし、強いてはコンピュータとしての資質もイマイチ、 と言うことになりましょう。

自作を好む人は汎用性(カスタマイズ性といいかえてもいい)を好む人だと 思います。お金以外の面で物理的重圧の少ない静音・キューブPCが人気があるのは さもありなん、と言う感じ。

その意味では、 静音で、とても小さく、よけいな周辺機器の付いてこなく、 オマケにそこそこ安いMac miniは真のコンピュータだと猫は太鼓判を押してしまうのです。 (そしてそれこそがハッカーの求めるコンピュータの姿です。)

やさしいUNIX入門

突然ですが猫はハッカーじゃありません。 だってUNIXが全然解らないんですもの・・。

今の猫は身も心もゲイツ様の奴隷。 だってMSDN Subscriptionに契約しちゃって居るんですものっ! (ああ、高いわぁ・・。) でもUNIXを手足のように使えるハッカー生活には強いあこがれがあるのです。

LinuxやFree BSDを導入するのは実はそれほど難しいことではありません。 雑誌の特集なんかを見ながら適当にパチパチやればLinuxマシンのできあがりです。 でもでも、その作った環境を日常的に使い続けるのは難しいことです。 そばに甘ぁいWindows環境があれば、ついついそちらを使ってしまいます。

甘いモノを立つには、もっと甘いモノを用意せよっ!!!

と、いうわけで、Max OS Xならば、 UNIXでありながら、甘い、あまぁ〜い環境であり、 絶対日常で使い続けられるという自信が持てます。 よしんばUNIXとして使いこなせなくても、 コンピュータとして使うのはいくら何でも出来るんだわさっ♪

そう、ハッカー的な素養を持つまだハッカーになっていない人にも、 「Mac OS Xを備えた自己主張しないマシン」 Mac mini は大変魅力的なんです。

|++ month top ++|

03月10日(木)

ようやく注文していたMac miniが届きました。 猫も念願のマカーになることが出来たってモンですたいっ!(←どこの人^^;)

わーい、Macminiが来ました♪

と、いうわけでようやくMac miniが来ました。 なんといっても箱からしてうれしいです。 ゲーム機の外箱より小さいのは感動です。。

Mac miniの箱
Mac miniの箱

Appleのパッケージングは嬉しいということをよく耳にしますがホントに嬉しい。 うきうき気分であけていきます。

あけるあける
あけるあける

ビニール包装を破る瞬間です。 「あたしのものになったのね」気分で胸がいっぱいになる瞬間です。

オープンベール
オープンベール

それにしても小さいです。 買う前は「Dreamcastとおんなじくらいかしら」と思っていましたがとんでも無いっ! 二回り以上小さいんです!!

DCと比べる
Dreamcast と比べる

そんなわけで床面積はDCよりも2まわり小さいゲームキューブと比べます。 う、ほとんど同じだわ。 どうやら 2Mac mini = 1ゲームキューブかしら。

GCと比べる
ゲームキューブ と比べる

えいっ、重ねちゃいますっ。

トーテムポール
トーテムポール

購入前はよくマッチすると思われた FKB-91JUMですが、 実際にMac mini と組み合わせてみると大きすぎる・・(TT)

FKB91JUMとマッチ
FKB91JUMと組み合わせてみる

OS Xの日本語キーボードを認識しない問題と併せて キーボードは再考しなくっちゃだわ。

|++ month top ++|

03月08日(火)

前回はPythonのシンタックスのうち、 特徴的で簡単なものを説明しました。 いろいろ変わっているところは多いのだけれど、 便利で合理的なところだから、気に入ってもらえたかと思います。 なかなか素敵なプログラム言語でしょ?

Pythonは 「ライト・ウェイト・ランゲージ」と言うモノに属します。 Perl、Ruby、PHP と言った言語と同じカテゴリです。 ここら辺の言語の特徴はとても動的だということです。

「"動的"っなぁに? 変数宣言が要らないこと?」なぁんて方に、 今回は、「動的ってどうアクティブなのよ」ということを コードの実行モデルと併せて少し説明します。

なんでも「実行」(ぬくぬくPython #3)

前回のソースコードをチョット見てみましょう。

inoki.py
# 関数 inokiKiai # # 某イノキさん風の気合いを # コンソールに出力する関数です。 def inokiKiai(): # とりあえずご挨拶 ----------------- print "いくぞ〜っ!" # 雄叫びを上げる(1、2、3、だ〜!!) -- cnt = 1 while cnt <= 3 : print "%s、" % cnt , # 「"%s ..." % hoge」 は、format構文です。 cnt += 1 print "だ〜!!" # 関数を使ってみる inokiKiai()

これを見て素直に説明するなら「inokiKiai関数を定義して、それを使っているんだねぇ」と 思うかもしれません。でも、それは違います。 「def」は「定義」じゃありません。 関数オブジェクトを作って、 それを変数に代入する、ということを実行する「文」なのです。

def文

試しにこんなのをつくってみます。

deftest.py
#coding: shift-jis print "コードが実行され始めました" print "関数を作成します" def hoge( str ): print str print "関数を使用します" hoge( "ほげ" )

pythonでは、C言語のように関数の中にしか文を記述できないことはありません。 (JavaやC#のようにクラスの中にしか関数や文を書けないとうこともありません。) なのでこういう 文と関数定義(・・じゃないんだけれど)のゴッタ煮も可能なんです。

これを実行するとこんな結果になります。

D:\pg-works\python>deftest.py
コードが実行され始めました
関数を作成します
関数を使用します
ほげ

なんだか本当に頭から順番に動いているようにみえますね。 じゃあ、def文と関数コールの順番を逆にしてみましょう

D:\pg-works\python>deftestrv.py
コードが実行され始めました
関数を使用します
Traceback (most recent call last):
  File "D:\pg-works\python\deftestrv.py", line 7, in ?
    hoge( "ほげ" )
NameError: name 'hoge' is not defined

あらら・・。エラーになってしまいました。 「え〜っ!?」と思うかもしれません。今時の言語ならソース上の順番なんて関係ないように作らなきゃ手抜きよ、 と言われちゃうかもしれません。 でもいいんです。なぜかというと・・・。

って、答えをいきなり教えてしまっては面白くありません。 チョットした実験をしてみましょう。

実験前知識 〜モジュールの説明

でも実験の前に基礎知識。知ってる人は飛ばしちゃってください。

Pythonのソースコードファイルは、 実行時にはそのまま「モジュール」という構造になります。 (モジュール名は自動的に拡張子を除いたファイル名になります)

Pythonの実行時構造は以下のようになっていて、 それぞれソース中の「コード全体」「class文」「def文」になります。

モジュール(←元:ソースコードファイル全体)
クラス(←元: classステートメント)
関数(←元:defステートメント)
(※クラスの中にいる時は「メソッド」と呼ぶ)
関数(←生成元:defステートメント)

Pythonは、トップレベルの構造としてモジュールがあり、 その下には関数やクラス、そして単なるコードや変数を好きに配置できるようになっています。 なので、大規模な構造をもったプログラムも、 ちょっとしたスクリプトも同じように書くことが出来るのです。

さて、各構造はそれぞれ独自の名前空間(シンボルの集まり)を持っています。 (シンボルとは変数名、関数名、クラス名、などなどです) Pythonにはこのシンボルの一覧を取得する 便利なビルトイン関数 dir があります。

dir()

のようにつかうと、 現在いる構造のシンボルを全部リストとして出力してくれます。 (引数を指定すれば引数で指定した構造のシンボルのリストを返します。)

実験開始♪

前口上が長くなりました。 ようするに dir() 関数を使ってモジュールの中に今 どのようなシンボルがあるかを見ながら動かしてみようと、そういうわけです。

deftest.py
#coding: shift-jis print "コードが実行され始めました" print dir() # 関数の作成 --------------------------- def hoge( str ): print str print "関数を作成しました" print dir() # 関数の使用 --------------------------- hoge( "ほげ" ) print "関数を使用しました" print dir() # 変数の代入 --------------------------- piyo = "ぴよ" print "変数への代入をしました" print dir()

これを実行するとこんな感じです。

D:\pg-works\python>deftest.py
コードが実行され始めました
['__builtins__', '__doc__', '__file__', '__name__']
関数を作成しました
['__builtins__', '__doc__', '__file__', '__name__', 'hoge']
ほげ
関数を使用しました
['__builtins__', '__doc__', '__file__', '__name__', 'hoge']
変数への代入をしました
['__builtins__', '__doc__', '__file__', '__name__', 'hoge', 'piyo']

見ての通り、def hoge():文を実行すると、 モジュールに キー 'hoge' が追加されたのが解ります。 オマケにモジュールレベル変数 piyoへ値を代入すると、 同じように モジュールに キー 'piyo' が追加されました。

このように def文による関数定義のように見えるモノは 変数にリテラルを代入する文(pythonでは初代入時に変数が生成されるので 正確には「生成して代入」ですね) おまったく同じく、 モジュールレベル変数に 関数リテラルの代入を実行する文 であるのです。

そして注目したいのは、 deb文が実行される、正にその直前まで、 hogeというシンボルは無いのです。 その直前までの世界には hoge が存在しません。 もしかしたら別の未来では hoge は変数だったかもしれませんし、 クラスだったかもしれません。 はたまた、モジュールだったかもしれないのです。

このように、「定義」で作り上げる「実行前から何もかも決まっている世界」ではなくて、 実行時に世界の構造そのものが組上がっていく、 これを「動的」といい、Pythonは動的であるために、関数が実行中の 任意のタイミングで「生成」されるのです。

答えあわせ

答え合わせ、というか種明かしです。 (名前空間だとかシンボルだとか、抽象的な概念は 大切だけれど、ピンとくるのが難しいですので、 実装(= タネ)を知ってしまうのも良いことです)

Pythonのオブジェクトの実体はディクショナリ(辞書)です。 ええっと、ディクショナリというのはこういうの。

# ディクショナリの生成
a_dic = {}

# ディクショナリに値を格納
a_dic[ "neko" ] = "にゃ〜"
a_dic[ "inu" ]  = "わんっ!"
a_dic[ "baku" ] = "ばくばくぅ〜♪"

# ディクショナリから値を取り出し
print a_dic[ "neko" ]           # 「にゃ〜」と出力

ようするに、キーに文字列が取れる配列のことです。[1] 連想配列とかハッシュとかの名前でも呼ばれますね。

で、Pythonで名前空間を持つモノ――モジュールやクラス、関数の正体は実は ディクショナリなんです。 名前の階層構造を作る全ての要素は、それぞれが一つのディクショナリで作られます。 その層の中で生成された変数や関数は 変数名(またはクラス名・関数名)をキーとしてそのディクショナリに追加されていく、 という仕組みになっているのです。

ざっくばらんに言うと定義のように見える

thisModule.py
class a_class(): def one_method( self ): pass

は、

thisModule.hoge
thisModule["a_class"] = new classClass(); # "class"という種類のオブジェクトを # 作ってthisModule辞書に格納 thisModule["a_class"]["one_method"] = new functionClass(); # "function"と言う種類のオブジェクトを # 作ってa_class辞書に格納 # ↑ ファイル名をしたディクショナリになっているのがミソ

のような感じの処理を実行する「文」という訳なんです。[2] (※ このコードはC系っぽいシンタックスの擬似コードです。Pythonじゃないですよ。念のため)

[1] Pythonの場合、正確には ディクショナリのキーになれるのはオブジェクトであれば何でもよいです。 例えばタプルとかと使って、

a_dic = {}     # ディクショナリの作成
a_dic[ (2003, 52, 4, "USB PS/2") ] = "Kensington Expert Mouse 7.0"

のようなことも出来ます。

[2] ちょっと嘘です。こんなに単純じゃなくて、 もっといろんな値がセットされてってます。

おまけ:関数オブジェクトを覗いてみましょ♪

と、言うわけで、Pythonの関数は オブジェクトです。 とは言ってもあんまり実感してもらえないかもしれません。 そこで、ちょっとだけ「関数がオブジェクト」なところを 見てみようかな、と思います。 (この項は「おまけ」なので、オブジェクト指向の「オブジェクト」がよくわからない人は 読み飛ばしちゃってください。

関数の中身を覗いてみる、ということで、 まずは覗かれる関数を作ります。

functest.py (1/5)
#coding: shift-jis def hoge( pram1, pram2 ,pram3 ="デフォルト引数1" ,pram4 =4): """ 関数オブジェクトの実モデルを調査するための サンプル関数です。 """ arg1 = "ほげ" arg2 = 2

サンプルなのでシンプルで役立たずな関数を作ってみました。 もう既にdef文には見慣れたと思いますが、これまで紹介したのとちょっと違う点があるので すこし寄り道して説明します。

まず一つ、引数に「param3 = "デフォルト引数1"」のような、 イコールで値が代入されているように見えるのがあります。 これはデフォルト引数といい、 関数コール時に引数が省略された場合に デフォルトとして適用される値を設定します。

もう一つ、 関数ブロックのヘッダ行直後にある「"""..."""」で囲まれたコメントのような部分があります。 これはドキュメンテーション文字列と言います。 別に三重引用符でなくちゃいけないモノではなくて、文字列リテラルならなんでもOKです。 関数に対するコメントと思って問題ないですが詳しくは後ほど。

ではテストしてましょう

functest.py (2/5)
# hoge シンボル自体のプリント print "hogeの文字列表現" print " ", print hoge print ""

この部分が実行されるとコンソールにはこのように出力されます。

hogeの文字列表現
     <function hoge at 0x00A237F0>

()を伴わないシンボルは単に変数の中身を示します。 Pythonでは元のオブジェクトに復帰出来るように文字列化できないようなものの 出力は <>で囲まれてその内容をおしえるように 自身を文字列化するという紳士協定があります。[1]

次いってみます

functest.py (3/5)
# hoge の戻り値(return値を指定してない関数での戻り) print "hogeの戻り値" print " ", print hoge( "dmy" , "fake") print ""
hogeの戻り値
     None

関数は戻り値が指定されていない場合、 Noneを返します、ということ。あんまり面白くはない「へぇ〜」です。 次行ってみましょ〜♪

functest.py (4/5)
# hogeローカルシンボルテーブルにある名前 print "hogeのローカルシンボルテーブルにある名前" print " ", print dir( hoge ) print ""

これは先ほどモジュールに対しておこなった dir関数を hogeを対象に行うということです。

hogeのローカルシンボルテーブルにある名前
     ['__call__', '__class__', '__delattr__', '__dict__', '__doc__',
      '__get__', '__getattribute__', '__hash__', '__init__', '__module__',
      '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
      '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults',
      'func_dict', 'func_doc', 'func_globals', 'func_name']

おお〜、いっぱいあります。なんかもう関数のくせに生意気です。 (ジャイアニズム発動) ここら辺みると「関数もオブジェクト」というのが解りやすいのではないでしょうか。

と、いうわけで真打ち、関数オブジェクトの持つフィールドの中身を見てみましょう

functest.py (5/5)
# hogeのローカルシンボルテーブルの中身 print "hogeのローカルシンボルテーブルの中身" for symbol in dir(hoge): print " " , symbol , "=" , print hoge.__getattribute__(symbol) print ""

ちょこっと説明すると、

hoge.__class__

hoge.__getattribute__('__class__')

は同じことです。最初のようにシンボルをリテラル表記しちゃうと、 「for文で回しながら リストからシンボル名を取ってきてそれで値を取得」が出来ないので こういう書き方をしているだけです。

それでは結果を見てみましょう

hogeのローカルシンボルテーブルの中身
   __call__ = <method-wrapper object at 0x00A22C90>
   __class__ = <type 'function'>
   __delattr__ = <method-wrapper object at 0x00A22C10>
   __dict__ = {}
   __doc__ = 
    関数オブジェクトの実モデルを調査するための
    サンプル関数です。
    
   __get__ = <method-wrapper object at 0x00A22C90>
   __getattribute__ = <method-wrapper object at 0x00A22C10>
   __hash__ = <method-wrapper object at 0x00A22C90>
   __init__ = <method-wrapper object at 0x00A22C10>
   __module__ = __main__
   __name__ = hoge
   __new__ = <built-in method __new__ of type object at 0x1E0BAAC0>
   __reduce__ = <built-in method __reduce__ of function object at 0x00A237F0>
   __reduce_ex__ = <built-in method __reduce_ex__ of function object at 0x00A237F0>
   __repr__ = <method-wrapper object at 0x00A22C90>
   __setattr__ = <method-wrapper object at 0x00A22C10>
   __str__ = <method-wrapper object at 0x00A22C90>
   func_closure = None
   func_code = <code object hoge at 00A270A0, 
                file "C:\ZWORKS\pg\python\11_FuncTest\functest.py", line 7>
   func_defaults = ('デフォルト引数1', 4)
   func_dict = {}
   func_doc = 
    関数オブジェクトの実モデルを調査するための
    サンプル関数です。
    
   func_globals = {'hoge': <function hoge at 0x00A237F0>,
                   '__builtins__': <module '__builtin__' (built-in)>,
                   '__file__': 'C:\\ZWORKS\\pg\\python\\11_FuncTest\\functest.py',
                   '__doc__': '\n関数のオブジェクト実態を探るテストコードです。\n',
                   '__name__': '__main__',
                   'symbol': 'func_globals'}
   func_name = hoge

(ホントは凄い長い一行で出力されるところに適当に改行を入れてます)

__class__が 「functionクラス」だったり、 ドキュメンテーション文字列が __doc__に格納されていたり、 func_defaultsにデフォルトの引数値が格納されていたりと 結構興味深いですね。

以上のようにdef文はまるで関数の宣言のようですが、 その実態は functionクラスのインスタンスオブジェクトを作って それをシンボル(変数)に代入しているだけだったりします。 要は「関数定義」になれた脳へのシンタックスシュガーです。

[1] 正確にはPythonのオブジェクトには2種類の「オブジェクトの文字列化」メソッドが定義されていて、 __str__()「人間には解りやすいけれど、正確ではないもの」 と__repr__() 「文字列から元のオブジェクトを復元できるもの」が有ります。 __repr__() では「元に復元できる」のを努力目標としていて、 それが出来ないときは、"<...some useful description...>" 形式の文字列を返してください、 とPythonの紳士協定は決めています。

実はprint文で使われるのは__str__()の方なので(__str__()が無いオブジェクトの場合 二番手として__repr__()が使われる)文中の解説は実は嘘です。

|++ month top ++|

03月06日(日)

言語設計者にとって重要な問いは、「言語はシステムか?」だそうです。

言語が描く世界の姿とシステム――OSやマシンアーキテクチャ等 が描く世界の姿が 一致するとは限りません。 言葉の一面は認識の道具であるのだから、言葉を換えれば描き出される世界は変わってきます。 (たとえチューリング等価だったとしても!) だから、言語設計者は理想の世界を描くためにシステムを作ってしまうか、 ・・それとも道具性を重んじシステムと言語世界との折衷を望むか、 大きな問いを投げかけられます。

この問いは、いろんな種類の言語にとっても重要な問いでした。 でもことオブジェクト指向言語にとっては、非常に重要な問いであり、 「そもそもオブジェクト指向とは何か」とうレベルの 禅問答に発展しかねない、 危ういモノなのです。

世界で最初のオブジェクト指向言語 Smalltalkはこの問いに「Yes!」と答えました。 Simuraを母にCを父にもつC++は、この問いに「No!」と答えました。 そしてJavaやC#は・・・、「No!」と答えつつも陰でこっそり出来るだけ「Yes」を やっちゃっている感じでしょうか?(笑)

終わる世界

現行のメジャーなOS (WindowsやMac OS ,Linux やPC-UNIX)はその世界を 全てファイルとディレクトリによって描きだされる、 言ってみれば「ファイル指向」なOSです。

これらOSは、プログラムも、データも、入出力(COMポートのオープンがfopenだというは有名な話) すらも、 何でもかんでも「ファイル」で表現されています。[1]. (そう、プログラムのことを実行ファイルというでしょう?)

逆にオブジェクト指向ではこれらの全てが「オブジェクト」でなければいけません。 「ファイル」は振る舞いを持たないビット列のストリームにすぎないので、オブジェクトではありません。 これはオブジェクト指向言語が描き出す世界とは非常に相性が悪いです。

オブジェクト指向するならシステムがオブジェクト指向である方が良いのですが、 ビジネスやツールとして見た場合、 言語がシステムを包括してしまうと本末転倒になってしまうので、 [2]. 現在主流のオブジェクト指向言語は言語はシステムの歯車にすぎないと考えたものが主流です。

そんなこんなで、 現在主流のオブジェクト指向言語はメモリ中でしか「オブジェクトワールド」ではなくなるため、 システムが複雑になるのです。

[1] この発想はCとの親和性が高いです。 Cはデータではなくて変数に型があり、データは単なるビット列にすぎませんが、 同様にファイル指向のシステムにおける「ファイル」も同様だからです。 (注:オブジェクト指向はデータに型を持たせる考え方です。)

ちなみに「ファイル指向」はMULTIXが元祖らしいです。

[2] サーバサイドではこの限りではない。ユーザは結果のみを得られればよい為、 サーバーでどんなOSが動いていようと関係ありません。 詳しくはポール・グレアムさんの普通のやつらの上を行けを参照してください。 また、ZOPEはサーバサイドにオブジェクトワールドを構築してしまった好例です。

ファイル指向とオブジェクト指向

Smalltalkのように OSであり、言語であり、開発環境である、という 完全にオブジェクトだけからなる世界というのは、 実はとても簡単で理解しやすいです。[3] (すくなくとも「オブ脳」をつくれ、なんてマヌケな主張がもてはやされる余地がありません[4])

オブジェクト指向は、現実のシミュレートをする特殊用途を、 一般化すると、とてもコンピュータが優しくなるのでは? というのがスタート地点です。 かの有名なエピソード、ジョブズさんとゲイツさんが見てMac OSやWindowsで真似した ゼロックス パロアルト研究所の Alt というマシンのOSは、Smalltalk-80でした。

このSmalltalk-80は現実の机をシミュレーションしたものです。 現在のGUIが、常に画面に表示している「デスクトップ」とは 現実の机をシミュレーションし、そこにモノが置けるという、 シミュレーション的発想によります。

デスクトップに置いたものを開くと「ウインドウ」が開きます。 この「ウインドウ」とは、「別の例え話の世界をのぞき見る」窓のことです。 (既にウインドウの先は「机の例え話」の世界ではありません)

本当はそこから別の世界に突入する・・という至極解りやすい概念だったのですが、 現在のGUIは「ウインドウ」というよりも「パネル」に近く、 「ウインドウの最大化」なんていう、訳のわからない言葉が発生し、 ちっともシミュレーションじゃなくなってしまっています。(^^;

GUIがオブジェクト指向のまねごとをしていたって、 所詮現代のコンピュータは根っこをファイルに支配されたシステムなので、 結局 デスクトップは「ファイルブラウザ」以外の何者でもないのが現状です。 デスクトップに散らばるオブジェクトっぽいものは、 所詮はアイコン表示されたファイルにすぎず、 ダブルクリックされたときに実行されたるのは 関連づけられたアプリケーションです。 アイコンなので、オブジェクトとしての機能を持たないのです。 (本来は「時計オブジェクトをデスクトップに置けば、 時間は表示する」というのが正しい姿です。)

[3] Smalltalkではデスクトップにテキストファイルを作るが如く、 ユーザの操作でクラスからインスタンスオブジェクトが作られ、 これまた既存OSのテキストファイルのごとく、「削除」という明示てきな操作をされるまで オブジェクトが消えることはありません。 そもそもクラス自体がオブジェクトなので新しいクラスの追加も同様です。

[4] 「オブ脳」が無いとか、錯覚だとか言っている訳ではありません。 現在のコンピュータエンジニアの大半はファイル指向に脳を強く汚染されているため、 本来「より人間的な」考え方であるはずのオブジェクト指向を 自然に受け入れられないのです。

ファイル指向に強く汚染された脳はデータと手続きを混ぜて考えることが困難になっています。 人間としてのリハビリを、コンピュータを使うためにしなくてはいけない 状況こそがマヌケだと言う意味です。

眠りとともに終わる世界

それでもデータとしてファイルを取り込む場合は、 オブジェクトでファイルをラッピングしてしまえば良いのです。 OOPLでは大抵ではFileSystemオブジェクトみたいなのを用意してあって まずファイルをオブジェクトにカプセリングします。 (Javaのプリミティブ型のオブジェクトラッパーと同じ感覚になるのが面白いです。)

しかし現在のOSはファイル指向、 どんなに粋がってみたところで、ソースコードは「ファイル」になるし、 メモリー上のオブジェクトも、プログラムが終了すれば全員漏れなくお亡くなりです。 つまり、 ファイル指向なコンピュータを使うためのツールとしてのプログラム言語 (「言語はシステムではない」と答えたOOPL達)は、 オブジェクト指向をするにあたって大きな制約を持っています。 その制約とはオブジェクト永続化の悩みです。

ファイル指向でも「実行ファイル」を実行すれば、 そこに割り当てられたメモリは完全に実行ファイルの支配下になります。 ならば、メモリ上にオブジェクトワールドを構築するのは簡単な話です。 完全自治区なので好き勝手してしまっても問題はない、というわけです。

しかし、メモリはメモリ。電源を切ればいとも簡単に消えてしまうはかないものです。 コンピュータは情報を処理し、蓄積していくものですが、 メモリ上だけの世界では肝心の蓄積が心許ない状況になってしまいます。 なので、何らかの手段で保存しなくてはならないのですが、 「ファイル」にしろ「DB」にしろ、そこはオブジェクト自治区外なので、 簡単な話では済みません。

簡単な話では済まないのに、避けて通ることが出来ないのも嫌らしいところです。

本来オブジェクト指向では、一度つくったインスタンス オブジェクトは 明示的に消さない限り永遠に残っていてほしいものですが、 なにせメモリ上でしか生きられないため、プログラムを終了すれば作ったインスタンスも全部消えてしまいます。 (「世界」ごとなくなってしまうのですから!)

なのでインスタンスオブジェクトの中から、それを再現できるだけの情報を抜き出して、 ファイルに書き出すしかないのですが、これは大変な手間です。 そのほかにも完全に情報を抜き出すには、 オブジェクトのアクセス制限を反故にする必要があるなど、問題がやまずみで、 気軽にオブジェクトの永続化に手が出せないのが現実です。

起きるたんびに天地創造

インスタンスオブジェクトからデータを抜き出して もう一度インスタンスを作るための情報をファイルに書き出す。 ・・・これはホントに面倒くさいです。 永続化は一部のオブジェクトだけすればよいものではなくて、 それこそ世界を永続化したいのですから、そして世界のオブジェクトの数は 大変なものなのですから。

なので、結局一般的な対処法は「プログラムの起動毎にオブジェクトを生成する」こと。 神様が夜寝ちゃうと何もかも消えちゃうので、 神様は毎朝起きるたびに天地創造からやり直すのです。 確かに世界中のオブジェクトの状態のメモを取ることに比べれば楽ですが、 それにしてもプログラムの起動毎にオブジェクトを生成しなければならないなんて、あまりにも面倒すぎます。[5].

「オブジェクトを作るオブジェクト」がファイルになる・・・。

オブジェクト指向ではなんでもオブジェクトなので、 オブジェクトを作るモノも当然オブジェクトです。 オブジェクトを作るオブジェクトのことをクラスといいます。[6]

毎回オブジェクトを生成することに決めた現在のOOPLですが、 でもチョット待ってください。 クラスだってオブジェクトには変わりないのに、なんでクラスは 世界と一緒に消えてしまわないのでしょうか?

答えは簡単、クラスは大抵 「ソースコードファイル」やそれをコンパイルした「実行ファイル」という形で 既にファイルになっちゃっているからです。 この当然といえば当然の処置ですが、問題は多いのです。

なぜって、だってソースコードに向き合うのはプログラマなのですが、 そのプログラマが扱っているのはアクマでファイル。 一番オブジェクト指向しなくちゃいけない肝心のコーディングの時に ファイル指向しているんですものっ! これじゃあ、一生懸命計算しながら 他人と会話を強要されるようなモノ、 オブジェクト指向が難しいと言われても当然です。

このプログラマの負荷の大きさに対して、 言語設計者も手をこまねいていたわけではありません。 例えばJava。 改良型C++のフリをしてチャッカリSmalltalkの概念を出来るだけ持ち込もうとした トロイの木馬型言語のJava君ですから、 そこら辺もしっかり腐心しています。

Javaではクラスのソースファイルには クラスと同じ名前をつけること、 一つのクラスしか入れられないようにすることで、[7] なんとかオブジェクトのように見えるように頑張りました。 なるほど、こうするとファイルがクラスオブジェクトに見えるのですね。

これは一見よい「たとえ話」に見えるのですが、そうは簡単にいかない問題も抱えています。 実はファイルとクラスの粒度は決定的に違くって、クラスの方が一つ一つの規模が圧倒的に小さいのです。 ファイルというのは実はとても大きなものを想定しているのに対し、 クラスは既存言語で言えば「関数」よりもチョット大きいくらいの粒度が 丁度良いモノなのです。 (そもそも「ファイル」という言葉自体が、「何かを(たいていは紙を)まとめたモノ」、でしょう?)

そのためJavaではファイル数が爆発してしまうという問題も抱えてしまいます。 世の中はオブジェクトで溢れているものだけれど、 ファイルはオブジェクトほど溢れかえるのに慣れていません。 オブジェクトのノリでファイルを溢れさせてしまうと、 今まで一つのファイルにまとめていたドキュメントを クリアファイルに1ページづつ入れてバ〜〜ッと広げてしまうようなモノ、 結局管理しきれない散らかりようになってしまいます。

これは意外に深刻な問題です。

[6] 正確にはクラス指向のオブジェクト指向言語において、です。 どんなオブジェクトでもオブジェクトを作る雛形になれるOOPLもあります。 (そのようなオブジェクトをプロトタイプと言います。)

ただ、プロトタイプベースのオブジェクト指向言語はオーバーヘッドがかなり大きいのと、 やはり「クラス(分類)」という物の見方は解りやすいのとで、 クラスベースのオブジェクト指向言語の方が優勢なのが現状です。 しかし、クラスはオブジェクトに対する拘束具として作用する向きも強いため、 真にパワーのある言語となるには、足かせなりがちです。

[7] 正確には「Publicなクラス」です。 Javaもさすがに「あふれかえり現象」を考慮していないわけではなく、 プライベートな、、つまりあるPublicなクラスに従属しちゃうような小さなクラスは、 Publicなクラスにまとめても良い、と言う風にすれば 折り合いが付くのじゃないかしら、ということを狙いました。 でもJavaのコーディングは、クラス名を変えるたびにファイル名かえたり、 分割・結合にファイル名変更が絡んだり、とちょっと面倒くさいように猫は感じられます。 (こんなこと言うとJavaユーザさんから ツールで回避しろ、と怒られそうです。)

ちなみに MS JavaことC#では、ファイルの世界はファイルの世界と割り切って まったくオブジェクトと対応関係を持っていません。

二つの世界

オブジェクト指向するなら システムがオブジェクト指向である方が良いのですが、 ビジネスやツールとして見た場合、 言語がシステムを包括してしまうと本末転倒になってしまうので、 現在主流のオブジェクト指向言語は言語はシステムの歯車にすぎないと考えたものが主流です。

しかし、それはプログラマに脳にファイル指向とオブジェクト指向の ハイブリッドエンジンを構築することを要求しますし、 普通のPCユーザさんをオブジェクト指向に教育する機会も滅してしまっているのです。 (ファイル指向にはさんざん洗脳してるのにっ!)

オブジェクトにメッセージを送る・・、プログラマやユーザは コンピュータを操作するとき(コーディング含む)にはセンダ(送り元)オブジェクトとなって、 コンピュータの中の世界と外の世界がシームレスに繋がるわかりやすさが オブジェクト指向にはあります。[8].

本来ファイルベースの考え方よりもヒトに優しくなるために生まれたのがオブジェクト指向なのに、 ハイブリッドで考えることを強要したために、とても難しくなってしまったのが 現在の「オブジェクト指向」と呼ばれる技術です。

だから猫は、オブジェクト指向の習得は「言語はシステムである」に「Yes!」と答えた言語、 Smalltalkを使うことを強くオススメします。[9]

[8] Smalltalkではコードを書いたのち、それを選択してから「Do it!」というメニューを選びます。 これは「コード」というパラメータで Smalltalkにたいし「Do it!」というメッセージを送信する行為です。 このときプログラマは一つのセンダ・オブジェクトに過ぎません。

[9] これには一つ裏話があります。 現在のハイブリットを強いる環境では、「人に簡単」というオブジェクト指向のメリットは 殆どありませんが、もう一つのメリット「大規模プログラミングに強い」があるため、 もてはやされているのです。 (規模が大きいという敵はいつの時代でもプログラマの最大の敵でした。)

で、こうしたアプローチで有力なのは、C++の「クラス付きC」なアプローチではなく Smalltalkの土壌で育った「責務を持った一塊」というとらえ方の 「オブジェクト指向」の方だと猫は思います。

だって、UMLのギャング・オブ・フォーだって、 リファクタリングのマーチン・ファウラーだってSmalltalkerなんですもんっ!

|++ month top ++|

03月05日(土)

Pythonを使うようになって、C#やJava、Cでのコーディングにストレスを感じるようになりました。 プライベートなコーディングではほぼ100% Pythonになっています。

というわけで、(?)第一回目は Pythonのシンタックスのうち、他のメジャーな言語と比べて特徴的なものを 説明します。

Pythonシンタックスの基礎 (ぬくぬくPython #2)

Pythonはカッコのない言語として有名です。 コードブロックを表現するのにカッコ( {} )やbegin / end 構文を使いません。 では、なにでそれを行うのかというと、インデントです。

inoki.py
# 関数 inokiKiai # # 某イノキさん風の気合いを # コンソールに出力する関数です。 def inokiKiai(): # とりあえずご挨拶 ----------------- print "いくぞ〜っ!" # 雄叫びを上げる(1、2、3、だ〜!!) -- cnt = 1 while cnt <= 3 : print "%s、" % cnt , # 「"%s ..." % hoge」 は、format構文です。 cnt += 1 print "だ〜!!" # 関数を使ってみる inokiKiai()

すみません、プロレスファンじゃないので適当です(^^; で、これを実行するとこんな感じになります。

D:\pg-works\python\hellow>inoki.py
sys:1: DeprecationWarning: Non-ASCII character '\x8a' in file D:\pg-works\python
\hellow\inoki.py on line 2, but no encoding declared; see http://www.python.org/
peps/pep-0263.html for details
いくぞ〜っ!
1、 2、 3、 だ〜!!

そうそう、Windowsだとダブルクリックでも実行できるのですが、 Windowsのコマンドプロンプト(DOS窓)は閉じたがりやさんなので、 バグがあった場合、そのエラーメッセージが出力されても、 見る間もなくあっという間に閉じてしまいます。 なので、 コーディング中はコマンドラインから実行することをオススメします。

さて、本題に戻ってコードを解説すると、「#」は一行コメント、defは関数定義宣言です。 ちなみに変数は宣言がいりません。(代入によって作られます)

前回お話したとおり、Pythonはコードブロックをインデントで表します。 但し闇雲に字下げをしてけばどんどんブロックが作れるかというとそうではありません。 普通ブロックには、 たとえば、関数だとか、クラスだとか、制御文だとか、何かの意味がつきます。 なのでコードブロック先頭にはこの「意味」を示す文―― 一段低いインデントの末尾に「:」ついた行がつけられます。 これをヘッダ行といいます。

while cnt <= 3:                         # ←ヘッダ行
    print "%s、" % cnt ,                   # ┐ブロック本体
    cnt += 1                               # ┘

逆にヘッダ行のない突然の字下げはエラーとなります。

    print "あいうえお"
    print "かきくけこ"
        print "ABC"                        # この行でエラー

ブロックの終了は初めてインデントが少なくなる文が出現するところまでです。 ただし空行やコメントだけの行は「インデント量が少ない」とは取られず無視されます。 「ブロック」のシンタクスには特に関係ない、ということですね。

while count <= 3:                       # ←ヘッダ行
    print "%s、" % count ,                 # ┐ブロック本体

# コメントだけの行
    count += 1                             # ┘
print "おしまい"                           # ←この行の一行前までがブロック

インデントは Tab文字かスペースで行われ、 Tabは8スペースと同等と扱われます。 ちなみに猫はTab文字を愛用 & 4タブ( 1Tab = 4 Space)の人です。 Tab文字を使うかスペースを使うかは好みの問題なので どちらでも良いのですが、混在させるときは注意しましょう。 ・・というか、混在させないようにしましょう。

と、いう風に、「ヘッダ行 + インデントされたコードブロック」が基本なのですが、 一つ例外もあります。ブロックの中身が一行だけのばあい、こんな書き方ができます。

while count <= 3 : count += 1

なんでヘッダ行の最後に「:」が付くのか、解った気がするでしょ?

日本語対応

さて、気になるのが、

sys:1: DeprecationWarning: Non-ASCII character '\x8a' in file D:\pg-works\python
\hellow\inoki.py on line 2, but no encoding declared; see http://www.python.org/
peps/pep-0263.html for details

の部分。ようするにASCII文字以外が入ってますよ、という警告なのです。 猫はこのソースコードをShift-JISで作りましたが、当然アスキー文字以外の文字 (警告では0x8a)が入っています。(これはEUCでもUTF-8でも一緒です。) でも日本人としては日本語をソースに入れられない不便きわまりない。 実はこのエラーメッセージ、無視してしまっても良いのですが、 ちゃんとソースコードがどんなエンコードかを指定すれば良いだけの話、 簡単ですのでいれましょう。

ソースコードがどんなエンコードなのか、というのを指定するには、 ソースファイルの先頭行か2行目かに

#coding: shift-jis

のように書けば、ファイルのエンコードを指定することが出来ます。 正確には正規表現「coding[=:]\s*([\w-_.]+) 」にマッチすればいいわけで、 Pythonのリファレンスには、

#coding=shift-jis                      ←VIM用
#-*- coding:shift-jis -*-              ←Emacs用

のような書き方ができますよ〜、と書かれています。

また、UTF-8の場合、 ファイルの先頭にバイトオーダマーク(BOM)が付いている場合はUTF-8と宣言 されているものとして取り扱われるので、 ファイルの保存時に BOM付きUTF-8で保存するのが 楽でいい用に思えますが、 実はDOS窓ってShift JISベースのなので、今度はコマンドプロンプトにprintしたメッセージが化け化けになってしまいます。 うーん、あちらを立てればこちらが立たず、 コンソールベースのスクリプトを組むのにBOM付きUTF-8ファイルは向きません。

ただ、Pythonの標準的なGUIとして「Tk」というのを利用するのですが、 このTkは渡せるのがunicode文字列なため、 GUIベースでしか作らない、と割り切れば PythonはUTF-8でコーディング・・というのも悪くないかも。

print文

つきあいが凄く長そうな print文なので少し詳しく解説しましょう。 基本はこんな感じです。

print "こんにちは、世界。"
こんにちは、世界。

こうすると、コンソール上に「こんにちは、世界。」と表示されます。 ちなみにpythonのprint文はCのprintfなどと違い必ず改行します。 (Javaの printlnのようなモノです。) 改行させたくない場合は、

print "こんにちは、" ,
print "世界。"
こんにちは、世界。

のようにprint文の末尾に「,」をつけると改行無しで出力するようになります。

また、C言語でおなじみの書式編集ですが、 これは print文自体の機能ではなく、文字列の%演算子で行います。

"数%d と文字%s" % (256 , "hogehoge")

これは、

 [文字列] % [タプル]

という演算(式の評価)です。 タプルというのは配列みたいなもので、 ()で囲んだなかにカンマで区切りながらいろんなのを記述していく 構造です。(詳しくは次回、ということで)

こんな感じで演算した結果、書式編集された文字列が返りますので、 これをprintすればOKです。

print "数%d と文字%s" % (256 , "hogehoge")
数256 と文字hogehoge

また、print文はコンソールに文字を出力するだけのものではありません。

D:\pg-works\python\hellow>inoki.py >out.txt

こうすると printした内容が out.txt というファイルに書き出されます。 ちょっとしたツールを作るときに便利でしょう?

ループ構文の「else」

もう一つ、Pythonの面白い性質は、 ループ構文に「else」句があることです。

Pythonのループ構文は、while文とfor文です。 これらは特に目新しいモノではなく、普通のwhile文と、for文(ただし、C,C++ではなく、Java式の、またはC#のforeach文と同等) なのですが、そのどちらもelse句を持つという、 ユニークな特徴があります。

でも、「ループのelseって何だ?」ですよね。実はこんな感じなんです。

PrimeNumber.py
#coding: shift-jis # 割り切れるかどうかを判断する # # 引数で渡された数が 1以外の数で割ることが出来るかを # 総当たり式でチェックする。 # (つまり、素数かどうかを判断する関数) def isDivisible( base_num ): # 割ってみてあまりがでるかチェックする cnt = 2 while cnt < base_num : if (base_num % cnt) == 0 : # 余りが0なら終了 print "%d で割り切れます" % cnt break cnt += 1 # 全通りで割り切れなかったら、その旨を通知 else: print "割り切れる数はありません" # isDivisible() のテスト用UI # # 1以下の値が入力されたら実行終了 while True: base_num = raw_input("割り切れるかチェックする数 (ここに入力)→") base_num = int(base_num) # 数字を数値に変換 if base_num <= 1: break isDivisible( base_num ) print "おしまい"

これは総当たりで素数かどうかを判断するプログラムです。

ループ構文のelse句は、「break」や「continue」で ループが中断されず、ループ継続判定式によりループが終了した場合に 実行されるコードブロックを指定します。

ループ構文のelse句は他のプログラム言語では見慣れないモノですが、 「総当たりで何かをチェックして該当が無い場合は...」のような処理に とても便利です。このありがたみは実はwhile文よりも イテレータを処理するfor文の方が大きいです。 リストを順番に洗っていく処理などは良くあることなのですが、 else句を持たないループ構文ではフラグを立てたり、短いgoto文を使ったり しなくてはならないケースが結構あります。

一度else句付きのループ構文を味わってしまうと 他の言語でかなりじれったい思いをすること受け合いです。

|++ month top ++|

03月04日(金)

以前猫がばっさり切り捨てた サンワサプライのStreamですが、 否定的なレビューを起こすべきだったかどうか、 今でも迷います。

何軒か「無駄な買い物をしなくてすみました!」というメールを頂き、 そのときは「ああ、よかったぁ」と思います。 否定的なレビューの役割は、 同じ罠にひっかかるのを抑止するためです。 レビューを書く前にも、 見た目や店頭デモ機を触っただけでは解らない欠陥に 地雷を踏んでしまわれる方が後を絶たないという話は 良く聞いていたから、 そのうちの何人かでも回避できたなら、 このレビューを書いた甲斐もあるものです。

ただ、「じゃあ、もう買っちゃった人はどうなの?」という視点において 猫はこのレビューをUpしたことをちょびっと後悔しているのです。 既にStreamになれて、あの暴れ馬を使いこなしている方にとって、 家族の一員を否定されることはとても不快に違いありません。

愛着を感じて居るんですモノ、それを罵倒されることは 心地がよいわけありませんし、 既に良好な関係を築いているならそれを破壊しかねないレビューは、 土足で人のココロに踏み込んでいくような、 そんな迷惑きわまりないものだわねぇ・・・と思うのです。

サンワサプライ Stream を使いこなすっ!

しかし、しかしです。猫にはStreamを使いこなすことが出来ませんでした。 その独特なドングリを転がすかのように蛇行するカーソル移動に慣れることは 結局最後まで出来なかったのです。

復習! Streamのひみつ

Streamがなぜ「地雷」なのかをおさらいします。 トラックボールは「ころがる」と言いつつも、実際には 同じ場所で空転します。それを仮想的に「転がる」に見せかけるには 「どこを?」と要素が重要になります。

たとえば、ボールが回転しているとき、 極の点に床があると想像してみてください。きっと一ヶ所でコマのようにスピンしている姿が 思い浮かんだとおもいます。 同じ回転しているボールで、今度は赤道の部分が床が触れていると想像してみてください。 (もちろん床に向かって重力が働いているですよ。) 同じ回転にもかかわらず、勢いよくボールが転がりだしたと思います。

このように、空転しているボールを「転がっている」と解釈するとき、 床の当て方によってその運動はずいぶん違うモノになります。 なら、機械が想定している床と、人間が動かすときに想定している床が 大きくずれていたらどうなるか――これがStreamです。

出現! ストリーム・テクニシャン

Streamのイメージセンサはボールの右横に壁のように付いています。 「重力ペンキ」とか「2001年宇宙の旅」のような重力で壁を転がるボールというのは なかなか人間には想像しにくいものです。 結果、前後に転がしているつもりでも、機械側の視点でみるとスピンしながら転がっている風にしか見えない ・・・というのが、Streamのカーソルどんぐり挙動の原理です。

この秘密の挙動を制御するには、脳内で 「なぜかボールにかかる重力のだけが方向が右」な想像して動かすのがよさそうです。 猫も「重力ペンキが塗ってある、重力ペンキが塗ってある」というおまじないを唱えながら 頑張ってみたのですが、無念、どうしても上手く操ることが出来ませんでした。

うーん、猫には駄目なのね・・。と長らくあきらめていた猫ですが、 ひょんなところでStreamを操るコツを目にしました。 それはトラックボールファンさんの掲示板で、 Streamは使いやすいと語る方に、 最初は「たで食う虫もいるものねぇ・・」と変な関心をしていたのですが、 そこで説明された操球法と掲載されたハゲチョロのStreamの写真は、 なるほど、こういう風にすれば制御できるようになるかも、と 猫に思わせる説得力がありました。

その方、K-Hyodoさんの書込はこうでした。(勝手にヒトのうちの掲示板からの 引用、ごめんなさい。)

Streamは、左側の傾きが急なので、すっぽりと覆うようにつかんでしまうと、 第1、第2ボタンを押す時にホイールが邪魔になります。 そこで、手首をやや左にずらしてやるとボタンを押しやすくなるのですが、 その状態で人差し指がちょうどボールの左端にきて、ちょうど操作しやすい場所に来るのです。

ボールの左側面をちょいちょい、と人差し指の先っちょの横側あたりで なぞるように動かせばOK・・というのは、 Streamの構造上理にかなっています。 うーん、なるほどこうすれば頭の中の床想定と、 イメージセンサの床想定をうまく一致されることが出来そう、至極納得です。

と、いうわけで、やってみました♪

Streamの握り方
Streamの握り方

う〜ん、なるほど。 あいかわらずへんてこ挙動ですが、 これなら「練習すれば使えるようになるかも」と思えます。 特にドングリ挙動が軽減されるのがキモですね。

と、言うわけで攻略法な無いわけではないのねぇ、というのが新鮮でした。 やっぱり愛は勝つのね♪

|++ month top ++|

SEO [PR] おまとめローン 冷え性対策 坂本龍馬 動画掲示板 レンタルサーバー SEO