Island Life

2010/07/28

Gaucheにdocstringが無い理由

gauche-develあたりで昔書いたような気もするけど、日本語でも書いとこう。

gauche はドキュメンテーションに不安があるな。EmacsLisp に慣れてるからだろうか。
コードのすぐ側にドキュメント文字が置けるのは大きなメリットだと思う。

Lisp系言語は昔から、関数の中にドキュメントを書けて、REPLからいつでも参照できる 機能を持っていた(docstring)。Gaucheは敢えて伝統を破って、その機能をつけていない。 今後もたぶんつけない。

主な理由はふたつ。

  • Gaucheは効率的なスクリプトエンジンであることを第一の目的にしている。 つまり、毎回実行の度にソースが読まれてパーズされることが前提。 docstringは開発時には役に立つけれど、実行時にはただのオーバヘッドである。 (プリプロセスしてdocstringを外したスクリプトを作っておくという手はあるが、 プリプロセスするくらいなら事前にコンパイルしたって同じ手間で、 その手間をかけないからこそのスクリプトエンジンなわけで。)
    ある意味コメントもそうなんだけど、コメントのパーズの方が文字列のパーズより軽い。
  • そもそも、コードとドキュメントを近くに置くのは良くないと思っている。
    • ちゃんとしたドキュメントを書こうとすると結構な分量になり、コードと混ざって コードがひどく読みにくくなる。例:大きなJavaのプロジェクトのソース。 (但し、Javaは設計方針としてコードを読むことよりも既にあるAPIを呼ぶことの方を 重視しているふうであり、そうであるならばコードの読みやすさを犠牲にしても それなりのAPIドキュメントが確実に生成されることを重視するのは理にかなっている。 Gaucheの方針は違うけど。)
    • 読みやすいドキュメントというのは構成も含めて考えられるべきだが、コードに混ぜて 書こうとすると全体の構成がコードに引っ張られてしまう。(KnuthのWEBシステムは ドキュメントの構成が先にあり、コードはシステムによって並べ替えられる。) 個々の関数のクイックリファレンス程度なら関数ごとに独立してるからいいんだけど、 それとは別にちゃんと構成を考えたドキュメントはどっちにしたって必要。
    • コードとドキュメントはひとつの抽象物を別々の視点から記述したもの。 より記述されるものを明確にするには、なるべく別の方向から記述した方が良い。 コードとドキュメントを一緒にすると、似たような視点からの記述になってしまがち。 (Cf. コードと別にドキュメントを書く意味)。
    • これはワークフローによるけど、Gaucheみたいにドキュメントのソースが 多国語化前提の場合、コードに埋め込むのはやりにくい。(もっとも、ソース内に 全言語を持っておくというGauche方式は言語数が増えると破綻するので、 コード中のドキュメントは例えば英語で統一しといてgettext式に 翻訳を別の流れでやるって手はある。)

開発中にすぐにドキュメントが参照できる、というdocstringのメリットについては 別手段で代替可能だ。Emacsを使ってるならソースから一発でinfoドキュメントに飛べるし (例: http://blog.livedoor.jp/naoya_t/archives/51350496.html )、 REPLから (info '関数名) とする手もある。 info 関数については ページ単位ではなくピンポイントで関数の説明に飛べるように工夫したいと思っているけど。 要は、「すぐに引ける」というメリットについては、ドキュメントがどこにあろうが 対応関係が機械的に作れれば何とでもやりようがある。

ただ、問題が無いと思っているわけではない。

  • 標準のドキュメントフォーマットがない。これは、未だ決めかねているという状態。 Gauche本体のように大きなものにはtexinfoが便利なんだけど、全てtexinfoでやれというのは 無理があるし。Perlがpodを、Rubyがrdを持ってるように独自に作っちゃう、っていうのも 車輪の再発明っぽくて億劫。わりと無節操に「色々なフォーマットが使えますぜ」っていうのも Gaucheっぽくてありかなとは思ってるんだけど。
  • 1ファイルで済むようなちょっとしたスクリプトやライブラリなのに、わざわざ別ファイルに ドキュメントを書くというのは確かに面倒。そういう場合はやっぱり ひとつのファイルにまとめておきたくなる。 実行時に負担にならなければいいので、他のスクリプト言語にある __END__ のように loadは何らかのマーカーを見たらそれ以降は読まない、ってことにすればいいんじゃないかとは 思ってる。

(追記2010/07/29 15:55:38 UTC): 別の表現を思いついた。Gaucheの設計方針のひとつは、 SICPにある次の文である。

プログラムは、人が読むために書かれるべきであり、 それがたまたま機械でも実行できるにすぎない。

したがって、言語機能の選択基準の一つは、「いかにコードを読みやすくするか」 という点にある。コードの理解を助ける目的ならば、 関数毎にコメントやアノテーションでその意図 (whyの記述) や 事前/事後条件、トリッキーなコードの説明などを書いておくのは良いことだ。 でもdocstringはコードの理解を助けるための文書ではない。 それはAPIを使う人のための文書だから。

たまたま、APIを使う人のために最適な文書と、コードを理解するために最適な文書が 一致するということはあるかもしれない。でもそうでないことの方が多いだろう。

だとすれば必然的に、docstringとコードを同居させるには、「コードを読みやすくすること」 か「APIを使う人に役にたつこと」のどちらか、もしくは両方を犠牲にするしかない。

Tags: Gauche, Lisp, Programming

2010/07/27

主観で何が悪いのだろう

この記事自体には特に異論はないのだけれど(特に取り立てて書くようなことでもない、とも思うけど)、 それに対する反論というのが興味深かった。

以下、この事をTwitterで紹介した際にあった面接を担当しているであろう方々からの主な反論を紹介します。

  • 「印象採用=好き嫌い採用」なんて論外。採用担当者は最後まで自分の第一印象を疑って面接をするように訓練されています。可能な限り主観を排除せよと。全く逆の考え方で驚きました…
  • 第一印象はあてになりません。恋人を選ぶのではなく仕事を成功に導くためのパートナーを探すのだから主観は排除するよう努めるべき
  • 当社ではそういうことにならないように、明確に評価基準を定めています。その基準は社員の人事評価基準に則っています。質問項目も決まっています。こんなに大事なことを、コミュニケーション能力とか面接官の印象とか、そんな曖昧なことで判断するわけにはいきません。

これらを読んで思ったのが、ちゃんと面接官を専門に担当する人々もいるということを知りました。プロの面接官は明確な評価基準を持っていて、印象になるべく左右されないように努めているようです。

主観で面接したら何が悪いの? いや、主観を排した面接がだめだ、っていうんじゃなくて、 主観で取るかどうかというのは、面接のゴールにはあんまり関係ない話じゃないかなあ。

面接のゴールというのは、欲しいポジションにベストマッチな人を選ぶってことだけど、 それが達成できたかどうかっていうのはすぐにはわからない。長期的に一緒に働いてみて 始めてうまくいったかどうかがわかる。歴史の長い、変化の少ない組織なら、 「こういう基準で選ぶと当たりが多い」というノウハウが明文化可能かもしれないから、 そういう客観的基準で選べばいいだろう。歴史が短かったり、変化が必要な組織なら、 逆に基準なんてわかりようがないのだから、面接官のセンスという一種の主観に頼らざるを得ないだろう。

一般的に対応できる方法が無い以上、一般的に適用できるノウハウというのは メタな基準にならざるを得ない。それはつまり、この一点だ。

  • 「採用担当者が、自分の判断に責任を持てる仕組みであること」

これが保証されていれば、印象で選ぼうがチェックリストで選ぼうがサイコロで選ぼうが どうでも良い。採用担当者が自分が責任を持てる方法を自分で選ぶだろう。

この議論を進めるならば、多くの職場にとって有効度が高いのは、

  • その人が採用されたら一緒に働くことになるであろう人間と、 その部門のパフォーマンスに責任を持つ人間が面接をする

といことになる。同僚や直属の上司は、一緒に仕事しにくい人を選んでしまったら 後々大変だろう。一方で、部門責任者は長期的なアウトプットに責任を負わなければ ならないので、単に仕事しやすいだけの仲良しクラブになってしまうことは避けようとするだろう。 また、そのポジションに必要とされる能力というのを最も的確に判断できるのは、 その専門性を理解している人間である。その点にも、現場経験者が面接をする重要性がある。

この議論の裏返しで、最悪の面接スキームとは、

  • その人が採用されても一緒に働くとは限らず、 またその部門のパフォーマンスに直接の影響を受けない立場の人間が面接をする

ということである。例えば、人事部の人間が面接をする、とかね。

(念のため、日本型雇用がどうの、って話はわかってて書いてる。 言いたいのは、将来もそれでやってけるの? ってこと。)

Tag: Career

2010/07/15

JRE hassle

Hudsonをちょっと手元 (Ubuntu 10.04) で試そうと思った。 オフィシャルページを見るとhudson.warをダウンロードして java -jar hudson.war とだけすれば良いらしい。おお、簡単ではないか。

簡単ではなかった。

  • アップデートしたばかりでまずjavaを入れてなかった。とりあえずapt-getでgcj入れとく。
  • hudson走らせると何かクラスが見つからないというエラーで初期化時にこける。
  • ぐぐるとどうもgcjでは動かないらしい。
  • apt-cache searchで探して次に目についたopenjdkで試す
  • 今度はjava.io.IOException: Operation not permittedなどのwarningが出て、httpでつなぐと「ちょっと待ってくれ」という画面から進まない。
  • さらにぐぐるとどうもsun-java6を使うのが無難らしい。
  • https://help.ubuntu.com/community/Java を参考にするが、 universeを探してもsun-java6なんて無いぞ。
  • Bug trackerの議論を追っかけて このブログに到達。partner repoを見なくてはいけないらしい。
    add-apt-repository "deb http://archive.canonical.com/ lucid partner"
    apt-get update
    apt-get install sun-java6-jre sun-java6-plugin
    update-java-alternatives -s java-6-sun
    
  • 再び走らせる。あれ、またjava.io.IOException: Operation not permittedだ。
  • ぐぐる。今度はfirewall絡みらしい。
  • こちらを参考に firestarterの設定をいじって再起動。
  • 今度こそ成功。

こんなことは珍しくはないので、特定のソフトウェアに責を帰するつもりは ない (多分GaucheやCLで何か動かそうとする人も似たような苦労をしてるはず) けど、 いくつか考えのネタは得られると思う。

ランタイムの配布の問題

時々、処理系の機能として「単独の実行ファイルが作れるか」ということを問題にする人が いるのだけれど、そういう人が本当に欲しいのは大抵「ファイルひとつコピーすれば 動く」という話だったりする (Cf. WiLiKi:Gauche:StandAloneProgram)。

んで教科書的回答は「ターゲットにランタイムが入ってればいいんですよ」ってことに なるだけど、十分に主流になったJavaでさえ未だにランタイムではまることがあるって ことは、もっと深いところでの解決が必要なのかもしれない。

というか、ランタイムのことを気にしないでもアプリを配布できる言語って 今でも事実上Cくらいしかないのかなあ? それって、OSの主要コンポーネントも そのランタイムを必要としているから、という理由が大きいよね。 まああとAPIが十分に枯れてるって要素もあるけれど。

とすれば、ランタイムを気にしなくても良くなるにはその言語がOSの主要コンポーネントにも 使われて、かつAPIが十分に枯れることが必要になる。でも発展途上の言語にとっては ちょっと無理な要求だ。javaでさえ苦労してるのに。

複合した問題の切り分け

今回、firewallとの干渉があったわけだけど、 ランタイムの問題があったせいでちょっと遠回りした感がある。

複数の問題が同時に起きていることはよくあることで、 問題を切り分けてひとつづつ解決するしかないのだけれど、 そのメタ手順自体はなんだか昔から全然変わってない。 もう少し、なにか賢いサポートがあっても良いんではなかろうか。

git bisectの発想に良い筋を感じる。あれは問題そのものを解決してはくれないけれど、 問題がどこで生じるかを調べる決まりきった手順を自動化してサポートしてくれる。

複合問題の切り分けでは、関係する要素をひとつづつ変えて試す作業を 最悪で全てのパターンについて行う必要がある。ただ、ある組み合わせで うまくいったら/いかなかったら他のいくつかの組み合わせは試す必要がない、 というケースはあるので、うまくテスト方法を選べば大幅に 枝刈りできる可能性もある。

システムレベルの問題なら、変更要素は「何をインストールしたか/しなかったか」と あとは各々の設定の切り替えが主なものなので、そのへんをカバーしてくれる テストサポートツールというのはあり得るんじゃなかろうか。

Tag: System

2010/07/14

少し前から右手親指の付け根が痛んでて、 腱鞘炎になったらやだなと思ってたんで、 日本に行った時、本屋で目についたこれを購入。大当たりだった。

本書で「親指の炎症を引き起こす危険が高い」とされている、

  • 親指主導の動き (橈骨を中心に手を回転させようとする / 手首が尺骨側に曲がりがちになる(尺側偏位))
  • 親指をいちばん根元の関節(手根中手関節)ではなくその次の関節(中手指節関節)から動かそうとする

に見事当てはまってた。自分が弾いてるビデオを見ると、不自然な尺側偏位があることと、 手根中手関節を動かす腱が緊張しっぱなしで関節を固めてしまってることがよくわかる。 そして痛みは確かに中手指節関節を動かす腱の腱鞘にあるようだ。

尺骨から小指を軸として意識すると、確かに親指の緊張が抜けてうんと楽になる。 ただ、これまでの弾き方が習慣になってしまっているので、よっぽどゆっくり弾かないと すぐに前の形に戻ってしまう。しばらくゆっくりさらってリハビリしよう。

この本は手の使い方だけでなく、全身の骨格と筋肉を意識することを論じている のだけれど、芝居での身体の使い方と重なる話が多くて興味深かった。

Tag: Piano

2010/06/28

アセンブラをぶっとばせ

http://twitter.com/vitroid/status/17262472219

開発者の生産性を上げるために新しい言語が創られる。速けりゃいいならアセンブラで書けばいい。 RT @osiire: これは私の周りの狭い世界では逆。 > "むしろ大部分のコードは今以上の性能を求められてると言えるんじゃなかろうか。" http://bit.ly/bDlkJS

「速さが欲しいならアセンブリで書けばいいじゃない」っていうのは、 ひとつ重要な条件を見落としてるよ。仕事で開発してるなら、 開発期間っていうのはコストだから、上限がある。 従って求められているのは、「所定の時間内で速いコードを書く」っていうこと。

最適化は時間内にどれだけ色々なアプローチで「実装→計測」のサイクルを 回せるかっていうのが決め手だが、アセンブリや低レベル言語で書いてる場合、 アプローチを切り替えるコストがばか高い。別のアルゴリズムを試したい 場合や、コードに影響を与えるパラメータを変えて実験したい場合 (簡単な例では、ループのunrollingをいくつ単位でやるか、とか) に手間がかかるからね。

だから、「開発者の生産性を上げる」ことを性能低下の免罪符にする 必要は無いんだ。むしろ、 性能を上げるためには開発者の生産性を上げることが必要なんだ。

言語/処理系設計上のトレードオフとして、開発者の自由度を上げると 処理系の負担が増えて性能が低下する、ということはある。例えばいつでも 動的にコードをすげ替えられる方が開発は楽だけれど、処理系は 静的に解析できる部分が減って最適化しにくくなる。 でもそここそが処理系作成者が頑張るべきところであって、 処理系作成者が開発者の生産性を上げることを性能低下の言い訳にするのはまずい。

あ、でも勘違いしないでね。「速ければ速いほどいい」って言ってるんじゃないよ。 「要求性能を満たしたい」って言ってるだけなんで、 言語/処理系のターゲットとしている領域で必要な性能が出てるなら それ以上頑張る必要はない。

ていうかさ。必要な性能を出せなかったらどんな言語を使おうが 意味無いよね。最初からそういう話をしているんだけどなあ。

★ ★ ★

あと、今でもとりたてて頑張らなくたって性能が出てるソフトウェアは たくさんあるだろう。それはそれで全然構わない。 けれどもちょっと考えてみて欲しい。今、使えているソフトウェアっていうのは、 今ある技術で「使える」性能に達しているものだ。だから 今あるソフトウェアの世界だけを見てたら、「性能は足りてるじゃん」と思えるだろう。 でもそれが世界の全てなのか? その世界の外側にも、書かれるべきソフトウェアがあるんじゃない?

Tag: Programming

More entries ...