Hatena::ブログ(Diary)

あどけない話

2008-03-14

プログラマの壁

プログラマに向いている人と向いていない人がいるそうです。

Jeff Atwood さんの「どうしてプログラマに・・・プログラムが書けないのか?」:

プログラムを書ける者とプログラムを書けない者の間にある大きな溝についてはよく知られているが、プログラマの職に応募してくる人間は、すでにこの溝を飛び越えているものだとばかり思っていた。明らかにこれは妥当な仮定ではないらしい。プログラムを書けないプログラマの面接で時間を無駄にしないために、FizzBuzzスタイルのふるい分けが必要ということだ。

どんなことでも向き不向きはあるでしょうから、これには納得いきます。しかし、プログラマになれる人の中にも、溝があるようです。

Joel Spolsk さんの「Javaスクールの危険」:

私のささやかな経験から言わせてもらうと、伝統的に大学のコンピュータサイエンスカリキュラムで教えられているもので、多くの人がうまく理解できないものが2つあった: ポインタ再帰だ。

溝はポインタ再帰だけではなく、他にもありそうです。

Paul Graham さんの「普通のやつらの上を行け」:

このプログラマ氏がパワーのスペクトルを見下ろしている時、彼にはそうしているという自覚がある。「ほげ」よりも力の弱い言語は、明らかに力が弱い。彼が慣れ親しんだ機能が無いからだ。しかし、このプログラマ氏が反対の方向に目を転じた時、彼は自分が見上げているのだということに気付かないのだ。彼が目にするのは、変てこりんな言語ばかり。多分、それらは「ほげ」と同じくらいパワフルなんだろうけど、どういうわけかふわふわしたおまけがいろいろついているんだ、と思うだろう。彼にとっては「ほげ」で十分なのだ。何故なら彼は「ほげ」で考えているから。

養老孟司さんの「バカの壁」を読んで、その考えが決定的になりました(この本自体はお勧めではありません。。。)。

数学くらい、わかる、わからないがはっきりする学問はありません。わかる人にはわかるし、分らない人にはわからない。わかる人でも、あるところまで進むと、わからなくなります。... それを考えれば、だれでも「バカの壁」という表現はわかるはずだと思っています。

「溝」より「壁」の方がしっくりくるので、「プログラマの壁」と言う表現を使うことにします。

まず、プログラマになれるかなれないかの壁があるのでしょう。なれたとしても、ある機能を理解できるかどうかの壁があります。その機能が理解できたとしても、次の機能が分るとは限りません。

ここでは、壁になりそうな機能を思いつくままに挙げてみることにします。

FizzBuzz

すなわち、簡単なプログラムが書けるかどうかという壁です。FizzBuzz が数分で書けないのなら、プログラマにはなれないでしょうね。

アルゴリズムとデータ構造

昔、授業で習ったユークリッドの互除法に感激し、この分野が好きになりました。新しいアルゴリズムを考えだすのには才能が必要です。僕にはその才能はありませんが、他の人が考えたことを学ぶことはできます。プログラミングをする際に、僕が一番頼りにするのは、この分野です。

最近は、この分野を軽視して、単にライブラリを呼べばいいとか、検索結果をコピー&ペーストすればいいという風潮があるように見受けられます。そう思っているのでしたら、ぜひ 「Joel on Software」を読んでみて下さい。いかに重要かが分るでしょう。アルゴリズムとデータ構造の勉強をしたければ、「珠玉のプログラミング」をどうぞ。(Pearl を珠玉と訳したところが、まさに珠玉です!)

Joel on Software

Joel on Software

正規表現

学生のときに苦労しました!その頃は、

  • 実用的な例題が載っている説明がなかったこと (a?b* みたいなものばかり!)
  • さまざまなツールの実装の差がまとまってなかったこと

などの理由により、学ぶのはとっても困難でした。

動かないのが、自分の正規表現のせいなのか、ツールがその正規表現に対応していないのか、はたまたツールのバグなのか判断できなかったのです。

「詳説 正規表現」(もちろん当時は初版)が出版されて、この混乱に終止符が打たれました。現在、正規表現を学ぶことは、そんなに難しくないのではないかと思います。

ただ、正規表現の中にも壁があるかもしれません。たとえば、ダブルクオートで囲まれた文字列正規表現が /"([^"\\]|\\.)*"/ であると理解できる人は少ないかもしれませんね。

正規表現では、「または」で表現するので、「かつ」で考えるとつまずきます。そこで、「かつ」で考えたことも、ド・モルガンの法則で「または」に直せると知っておくのも重要かもしれません。

詳説 正規表現 第3版

詳説 正規表現 第3版

ポインタ

僕はマシン語の後に C を学んだので、C のポインタは逆に分りやすいという印象を持ちました。。。配列ポインタの違いは、少し難しいかもしれません。

char table[10];
char *p = table;
printf("%d, %d\n", sizeof(table), sizeof(p));
 → 10, 4

C のポインタを習得する際に役立ったのは、「Cプログラミングの落とし穴」です。(まだ、売っていてビックリ!)

Perl5 はポインタ抽象化に失敗しているので、Perl5 でポインタを学ぼうとした人は、不幸かもしれません。

JavaJavaScript などは、ポインタだらけの言語ですが、うまく抽象化されているので意識することはありませんね。

Lispポインタだらけですが、普段意識する必要はありません。ただ、セルの利用効率を上げようと思うと、ポインタを意識することになります。

Cプログラミングの落とし穴 (新紀元社情報工学シリーズ)

Cプログラミングの落とし穴 (新紀元社情報工学シリーズ)

再帰

再帰が分らない人は、「The Little Schemer」をどうぞ。日本語で読みたいなら、「Scheme 手習い」の古本を探してみましょう。それでもダメなら、「リスト遊び」をどうぞ。

The Little Schemer (MIT Press)

The Little Schemer (MIT Press)

リスト遊び―Emacsで学ぶLispの世界 (ASCII SOFTWARE SCIENCE Language)

リスト遊び―Emacsで学ぶLispの世界 (ASCII SOFTWARE SCIENCE Language)

オブジェクト指向

最近は Java から入る人が多いようなので、オブジェクト指向はあたりまえかもしれません。

僕の学生時代は、まだオブジェクト指向黎明期で、間違った宣伝がたくさんされており、いろいろ誤解していました。間違った宣伝の例としては、継承による差分プログラミングが最たるものです。

オブジェクト指向では、

などの感覚を掴むのが重要だと思います。

また、「Rees Re: OO」を読んで、俯瞰した理解を得るとよいかもしれません。

高階関数

C で「関数へのポインタ」が分る人でも、高階関数でつまずくことがあるようです。関数の中で関数が定義され、それが返されるなんて想像できないかもしれません。

スコープがレキシカルのとき、返された関数クロージャとなります。JavaScriptクロージャを使ってプログラムを書くのは楽しいですよ。

Haskell を勉強すると、カリー化も役に立つことが分ります。

非同期

ネットワークプログラミングは、非同期で書くのが自然だと思うのですが、どうしても同期で書いてしまうようです。制御の流れが複数になると、理解するのが困難なのでしょうか?

Ajax のお陰で非同期にまたスポットライトが当たるようになりました。でも、Ajax の非同期は中途半端なので、別の方法で非同期を学ぶ必要があるような気もします。

遅延評価

UNIX のパイプを使っているなら、コマンドのレベルで遅延評価を利用しています。Haskell のように、遅延評価が基本となっている言語では、関数レベルで遅延評価が使えます。遅延評価だと意識さえしない程です。でも、IO が絡んでくると、順番が決まらないため、モナドを使わないといけなくなり、意識させられます。。。

日頃使っている言語に遅延評価の機能がなくても、遅延評価という考え方自体が重要です。たとえば、ファイルの内容を色付けして表示することを考えて下さい。まず最初に表示している部分だけを色付けし、残りは後から裏で色付けすれば、ユーザにストレスを与えることがありません。

Lispマクロ

Lisp では、データもプログラムも S 式です。これは、プログラムをデータのように加工して、別のプログラムを生成できることを意味しています。この加工を請け負うのがマクロです。マクロを書くと、Lisp を解こうとしている問題に適した言語に成長させることができます。

Lispマクロを勉強したい人は、「On Lisp」をぞうぞ。

On Lisp

On Lisp

Scheme の継続

僕も勉強中です。

モナド

いやぁ、もう大変です。

おやじですおやじです 2008/03/15 02:52 あと「クラスライブラリ」も壁になりますね。わかる人と、わからない人の落差がひどい。

kazu-yamamotokazu-yamamoto 2008/03/15 10:05 ああ、そうですね。どんな関数やメソッドがあるかは、長い間使わないと分りませんね。これは、根気の問題でしょうか?

naoya2knaoya2k 2008/03/15 14:10 Javaだとマルチスレッドですよ。

kazu-yamamotokazu-yamamoto 2008/03/15 17:11 naoya2k さん、こんにちは。
これは、非同期の部分に対するコメントですね? 残念ながら、僕は Java のスレッド・プログラミングの経験がない(toy プログラムしか書いたことがない)ので、コメントできません。つまらない反応で、ごめんなさい。

kazu-yamamotokazu-yamamoto 2008/03/15 17:22 書こうと思っていて忘れていた「アルゴリズムとデータ構造」を加筆しました。

wirewirewirewire 2008/03/16 01:14 モナドは大変だぁ。C/C++のマクロも結構落とし穴があったりなかったり。

errerr 2008/03/16 01:35 ネイティブな関数のリファレンスのみでがむしゃらに汚いソースを書いて再帰あたりは自分であみ出して(気付いて)欲しい。
そこまでいけたら壁を越えられる素質があるといえそうだ。

kazu-yamamotokazu-yamamoto 2008/03/16 10:42 wirewire さん、
C/C++ のマクロは、Lisp のマクロと違って、評判が悪いですね。D では、マクロがなくなっているようです。

http://www.kmonos.net/alang/d/2.0/comparison.html

kazu-yamamotokazu-yamamoto 2008/03/16 10:44 err さん、
僕は、どちらかと言うと、早めに再帰の存在を教えてもらって、しっかりと勉強してほしいと思っています。再帰も奥が深いので。単一関数による再帰の再帰とか、複数の関数による多重再帰とか。再帰は極めたと思っていたのですが、この前、モナドに再帰が出てきたときにさっぱり分らず、情けない思いをしました。

shibachoshibacho 2008/03/16 23:29 個人的にはC++とJavaの壁も結構あります。
「メンバ変数」なのか「プロパティ」なのか、
「メンバ関数」なのか「メソッド」なのか。

まぁ、オブジェクト指向的には後者の呼び方が普通なんでしょうが、、、前者の方が個人的に馴染み深いので会話するのに少々困っていたりします。

elecstaelecsta 2008/03/17 08:07 マクロなくなるのか・・・超便利なのに。
Cのマクロを多段で使うのに慣れてると高階関数が理解しやすいんですけどね。
Cで始めてMTしたときはそれまでの常識が覆されていっそ清清しい挫折を感じました・・・。

kazu-yamamotokazu-yamamoto 2008/03/17 10:38 shibacho さん、
困った問題ですが、慣れるしかないでしょうね。一回まとめてみると、すっきりするかもしれません。
http://d.hatena.ne.jp/kazu-yamamoto/20071025/1193280991

jj1bdxjj1bdx 2008/03/17 10:48 非同期という話になると,プログラミング言語だけじゃなくて,システムコールの実装も議論しないといけなくなるでしょうね.

kazu-yamamotokazu-yamamoto 2008/03/17 11:46 elecsta さん、
ご存知だとは思いますが、マクロが引き起こす問題は、プログラミング作法の1.4章とかCプログラミングの落とし穴とかに書かれています。
うろ覚えですが、D でマクロがなくなった理由の1つは、プリプロセッサで処理されると、コンパイラで情報が使えず、最適化に利用できないということだったように思います。

takano32takano32 2008/03/26 11:22 フレームワークも仲間に入れてください。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証