Cogito Ergo Sum. このページをアンテナに追加 RSSフィード

2011-06-30 Thursday

人生マラソンとの違い

 根性もない、負けず嫌いでもない、実生活ではすぐに挫けて諦めてしまう僕が、どうして100kmマラソンを完走できるのか、不思議でならない。マラソンはよく人生に例えられるが、最近人生マラソンとの違いについて考えていて、決定的な違いを見つけた。

 その違いとは、「マラソンは終わりが明確である」という点だ。例えば、100kmマラソンなら100km走れば必ず終わる。それ以上は一歩も走らなくて構わない。逆に言えば、100km走るだけでいいのだ。

 それだけでない。残り距離も明確だ。50km走れば残りは50kmだし、60km走れば残りは必ず40kmだ。

 マラソン大会ではよっぽどのことがない限りコースを逆走することはないので(稀に逆走している人を見かける。一度は通り越したトイレを目指している?)、どんなに小さな一歩でも、前に進み続けている限り必ず残り距離は減少していく。

 これが人生ではそうはいかない。どんなに頑張っても残り距離が全く減らないか、場合によっては増えていくような場合すらある(借金とか…)。力を振り絞ってゴールに辿り着いたと思ったら、「じゃじゃーん! 実はまだ中間地点でしたー!」なんて言われたりする。ゴール後に「さぁ、続けて第2ステージへお進みください!」なんてこともある。一向に終わらないのだ。

 僕はつい力を振り絞ってしまうところがある。人生において、ゴールだと思って力を振り絞って、実はそこはゴールではなかった、という経験をよくする。その途端に嫌になってしまうのだ。もう一切のエネルギーも費やしたくなくなってしまう。何だ、一生懸命やったのに騙された。馬鹿バカしい。そう思ってしまうんだよなぁ…。だから人生マラソンでは僕は頑張れない。いくら走ったって終わらないんだもん。最初から走らない。

 ところが、現実マラソンは必ず終わる。客観的な進み具合までわかる。「残り1km」の看板のあと走らなければならない距離は必ず1kmなのだ。

 だから僕は100kmマラソンを走り切ることができるのである。

2010-08-16 Monday

Lispをめぐる言説のウソホント?

 Lispの本を読んでいてLispというものがだんだんわかってくると、「Lispを学ぶとプログラミングのスジが良くなる」みたいな言説は嘘ではないかと思うようになってきた。

 Lispの魅力は、おそらくLispそのものを自分拡張してしまえるような柔軟さにある(条件分岐や繰り返しを行う処理もLispではただの関数マクロとして定義されており、当然、そういった関数マクロ自分定義することができる)。そういうレベルLispを使いこなすことのできる人ならそりゃあこの言語に魅了されるだろうし、優秀なプログラマだろう。だから「Lispは優秀なプログラマを魅了する言語である」ってことは正しいと思う。

 しかしそれは、「Lispを学ぶと優秀なプログラマになる」ということを意味しない。単に「優秀なプログラマしかLispを使いこなせない(し、使い続けない)」ってことなんじゃないかと思う。Lispを使いこなすレベルプログラマなら、どんな言語だって使いこなすだろう。そのときに使いこなし甲斐があるのがLispだというだけで。

 ほんの一握りの優秀プログラマを除いた多くのプログラマは、デファクトスタンダードではない言語を使い続けることはできないだろう。デファクトスタンダードがCならCを使うだろうし、それがJavaならJavaを使うだろう。それがLispならLispを使うだろう。

 で、Lispデファクトスタンダードになったときに、「やっぱりダメプログラマLispを使ってもダメなままだ」ということが明らかになるのではないかと思う。むしろ、Lispは制約が少ないぶんだけ、どんなにダメプログラムでも書けてしまうような怖ろしさがある。

 Rubyも凄く自由な言語だと思うのだけど(まぁ、Lispに比べれば大したことないのかもしれないが)、Railsの成功によってRuby人口が爆発的に増えて、そりゃもう信じられないようなヒドいプログラムもたくさん書かれているはずだと思う(Rubyにはそれを許す自由さがある)。プログラミング言語に限らず、どんなものだって大衆化すれば(一部の優秀な人たちだけが使っていた頃と比べて)全体の質は下がる。

 結局、制約の少ない言語でちゃんとしたプログラムを書けるのは特別に優秀な人に限られた話だと思うのだ。Javaなんかがルールだらけで堅苦しいのは、そうしなければ普通の人はちゃんとしたプログラムを書けないからなのだから。マニュアル通りに決まりきったことをやらせる、というのが全体の質を上げる手っ取り早い方法なのだ、たぶん。

 あるものがあったとして、それを使いこなしている人がそれを評価するときに挙げる(その「あるもの」の)性質と、それを全員に使わせるべきかどうかを検討するときに考慮すべき性質は異なる(それは単に「異なる」というだけで、必ずしもトレードオフの関係にあるわけではないと思う)。そういう当たり前のことに思い当たった。

 Lispという言語は確かに使いこなせる人にとっては最高の言語なのだろうけど、誰もが使いこなせる言語ではない(たぶん。今のところは。…って言うか、LispLisp的である限り)。

2010-08-10 Tuesday

久し振りにJava入門

 いつも文句言ってるクセにナンダカンダで毎月買っている「日経ソフトウエア」の最新号(2010年9月号)の特別付録が「完全保存版! コードでわかるJava & オブジェクト指向」で、一気に読んでみた。

 Javaに関しては、もう10年くらい前から数年おきにチャレンジしては決まって最初の壁で挫折していた。統合開発環境を使わず、メモ帳コードを打ち込んでjavacでコンパイルjavaで実行…、というのは骨が折れる。

 結局Javaは身についていないのだが、1〜2年ほど前にC#で1つプログラムを書き、15年くらい解消されなかった「オブジェクト指向に対する苦手意識」は克服できた。そのためか、今回この特別付録を鼻歌マジりの余裕シャクシャクで読んでいる自分自身を発見

 以前気付いたことなのだけど、オブジェクト指向概念がわからない人にとっては本当にわかりづらい概念であるのは、(まぁ、いろんな理由があるんだろうけど)1つはやっぱり説明の仕方が悪いんだと思うんだよね。

 今回の特別付録でも、(Java流の)オブジェクト指向の3大要素として「カプセル化」「継承」「多態性」を挙げているけれど(普通そうだと思うけど)、「クラスを作る立場」からの視点と「クラスを使う立場」からの視点とでは、これらは全然違って見えるものだと思うんだよね(入門レベルとしては、クラス自分で作って自分で使うわけなので、仕方ないのかもしれないが…)。「カプセル化」と「継承」は「クラスを作る立場」に立ったときに便利な機能、「多態性」は「クラスを使う立場」に立ったときに便利な機能、そうはっきり視点を変えて説明しないと何が便利なのかわかんないと思う。と言うか、オブジェクト指向プログラミグって、やっぱり「1つのプログラムをチームで作っている」状況を思い浮かべないと、何が便利なのかピンとこないものなんじゃないかなぁ。「カプセル化」してクラス内部を隠すのは、自分の作ったクラスを誰かに変な使い方されたら困るからなんだし。初心者自分1人で行うプログラミングだと、そこら辺の感覚がわかんない。

 入門記事によくある、「如何にも(悪い意味で)手続き指向的」というプログラムオブジェクト指向風のプログラムに書き換えるような例も、よく見てみると、良い例とそうでもない例がある。継承を利用した「差分プログラミング」みたいなことは、僕は「オブジェクト指向プログラミングとは何か」みたいなことを考えるときにはあんまり本質的なものじゃないような気がする。第1に伝えるべきは、やはり「クラスを使う立場からは一般論的なプログラムを書き、個々のオブジェクト固有の都合に関してはオブジェクト自身に解決させる」ということなんじゃないか(もちろん、そのために「多態性」を用いるわけで、その「多態性」を実現するために「継承」を用いて「差分プログラミング」するわけだけど)。

 それと、僕が1年半ほど前にようやく「オブジェクト指向の勘どころがわかった!」とガッテンしたのは、実は「インターフェースって便利だ!」と気付いたときなんだけど、紙数の少ない入門記事はもちろん、紙数の多いプログラミング入門書でも、インターフェースの説明って、「カプセル化」→「継承」→「多態性」の後にちょこっとオマケ的についてるだけで、本当に面白いところを説明する前に力尽きちゃってるような気がするんだよね(読者も著者も)。だけど、結局「オブジェクト指向って便利だ!」と思わせるためには、最初から「インターフェース」を目指して説明していくのがいいんじゃないのかなぁ。上記特別付録の中で「最近インターフェースベース設計が主流」と書いてあったので、その点もガッテン(ただ「最近」と言っても、その記事は2007年に書かれたものだったので、「最近」と言うほど「最近」の話ではないんだろうけど)。

 Javaづいてきたので、ついでにこれまで読んでいなかった連載記事「Javaで始めるプログラミング」(都元ダイスケ氏)を第1回から第5回まで通して読んでみたんだけど、変数のことを「ノートに書き込んだ情報につけた付箋のようなもの」と説明していて(「ノートに書き込んだ情報」ってのがインスタンスで、「付箋」が変数ね)フ〜ンと思った。このタイプの説明の仕方を始めて見たのはRubyの入門書だったんだけど、今では、intだとかdoubleだとかcharといった昔ながらの値型の変数より、参照型(オブジェクト型)の変数を扱う方が多いことを考えると、従来の「変数は値を書き込む箱のようなもの」という値型の変数をよくイメージさせる説明の仕方はスタれていって、参照型の変数イメージしやすい説明の仕方が主流になっていくのかなぁ〜と思っていた。実際にそうなりつつあるということなのかな。

2010-07-25 Sunday

ようやくわかった!

 僕は長い間「再帰的関数」の面白さがわからなかったのだけど、ようやくわかった。その面白さ(と怖ろしさ)は「多重ループの深さが実行時に(データの階層構造に合わせて)自動的に決まる」ことにある!

 だから、「(単なる1次元の、つまり1重の)ループ処理を実現している」だけの「階乗」の関数の例なんかは面白くなくて当然なわけだ。だけど、「ハノイの塔」や「クイックソート」は違う。

 考えてみれば、ハノイの塔やクイックソート関数再帰を使わずにWhile等を用いた通常のループ処理で書くことはできない。ループを何重にすればいいか決まらないから。

 だから、再帰処理の面白さは、(よく言われるように)「丸投げ処理でループ処理を実現できる」ことにあるのではなく、「与えられた要素の子要素に対しても同じ処理を行う」という(再帰処理の)記述を1回書くだけで、子要素にも孫要素にも曾孫要素にもヤシャゴ要素にも同じ処理を実現できるところにある。つまり、実行時にならないと入れ子構造の深さが決まらないような多重ループ処理を動的に実現してしまう点にあるのだ。す、す、す、凄っごいじゃん、それって!

 うわーっっ、再帰最高!

2010-07-24 Saturday

なんかちょっとわかったような気がする。

 数ヶ月前(?)に本屋で見かけて「そのうち読んでみたいな」と思っていた『初めての人のためのLISP(増補改訂版)』(竹内郁雄(著) 2010年 翔泳社)が図書館に入っていたので借りてきて読み始めた。確かに「天下の奇書」の評判通りムチャクチャな本で大変面白いのだが、哲学書みたいなところもあり、今となっては「初めての人」向けの本とは言えないと思う(元々1980年代前半に雑誌で連載されていたLisp入門をまとめた本なので、ギャグのノリがモロ80年代、というのも今となっては苦笑ポイント(苦笑))。

 そこで、同じく図書館で見つけた『リスト遊び』(山本和彦(著) 2000年 アスキー)を借りてきて読み始めた。これも2000年に出た本で「最近の本」とは言えないかもしれないが、「リストに対する再帰処理」に的を絞った良書だと思う。1,200円と安価なのも良い(僕は図書館で借りたわけだけど)。

 両方を同時進行で読んでいて、先月1年分をまとめて読んだ『日経ソフトウエア』の連載記事「魔法言葉 関数型言語を学ぼう」もまた読み直したくなってきたのだけど、僕は読んだページは破って捨ててしまっているので手元にない。早く1冊にまとめて特別付録としてつけてくれないかなー(秋頃、特別付録になるのではないかと踏んでいる)。

 で、『初めての人のためのLISP』の最初の4〜5章(全17章)の内容を踏まえて『リスト遊び』の最初の4〜5章(全8章)をジックリ読んでいて、Lisp構造的な秘密に気づいてしまったように思う。直感的には、それがLispのパワーを生んでいるものだろうとも思う。

 僕が中途半端に理解したところによると、Lispプログラムが扱うデータは「リスト」という形式で扱われることになっている。そして、Lispプログラムそのものも同じリストという形式で記述することになっている。つまり、Lisp世界では、データプログラムも同じ形式をとっている。

 そのことにはすぐに気づいたのだけど(と言うか、そう書いてあるから)、それが意味していることにはすぐには気づかなかった。昨日気づいたのは、両者が同一の形式をとっているということは、Lispプログラムデータを処理する原理と、LispインタプリタLispプログラム解釈実行する原理が同一だ、ということだ。

 プログラムデータを処理する。インタプリタコンパイラは「データを処理するプログラム」をデータとして処理する。それはどんなプログラミング言語だってそうだと思うのだけど(非ノイマンコンピュータのためのプログラミング言語とかだとひょっとして違うのかなー?とも思うが)、普通は(「普通」ってのは、CだとかJavaだとかBasicだとか)、プログラムデータを処理する原理インタプリタコンパイラプログラムを(データとして)処理する原理は異なっている(のだと思う。僕はインタプリタコンパイラ原理なんて知らないけど)。ところが、Lispでは、どうも両者が完全に同じようなのだ。Lispプログラムがやっていることはリストの処理であり、Lispインタプリタがやっていることもリストの処理である。データプログラムも同一の形式であるため、こういうことが可能になっている。

 そして、このフラクタクルな二重構造が、きっとLispの(他の言語にはない)パワーを生み出しているに違いない、根拠はないんだけど、そう確信した。たぶん、この二重構造はただの二重構造では終わらない。事実上無限に二重構造を生み出していけるはず(例えば、Lispプログラムを扱うLispプログラムを扱うLispプログラムを…扱う、という風に)。

 こいつは面白い


※ 「フラクタクルな二重構造」ってのは「今となっては苦笑ポイント(苦笑)」みたいなこと、って言うか、これは違うか。

2010-07-23 Friday

だんだんわかってきた。

 最近GaucheLISPの2大方言の1つScheme処理系。もう1つはCommon LISP)やLISPの本なんかをチラチラ眺めていて、関数型言語の魅力というものが少しずつわかってきた。

 まず最初に、

ということ。瑣末な例かもしれないが、予約語1つとっても(例えば、Javaなんかと比べて)かなり少ないと思う。文法規則もシンプル(特にSchemeがそう。Common LISPに関しては正直よくわからない)。自分を制限するものが少ない、というのは「プログラミングを通して自分自身を自由に表現したい」というようなハッカー気質に合っているのではないかと思う。

 それから

しかも、

  • そのある程度複雑な構造をもつデータから、「リストの先頭要素を取り出す」「先頭要素を除いた残りのリストを取り出す」というたった2つの操作だけで、どんなデータも取り出せること。

といった辺りがまたハッカー魂をくすぐるのだろう。

 その他に、

つまり、

 といった辺りもそりゃ、ハッカーとまでいかなくても、プログラマ魂をくすぐるよね。

 あと最近気がついたのは、

LISPバリバリ使うような人は普段UNIX/Linuxを使っているような人ではないかと思うので(純粋偏見ですが…)、UNIX文化にドップリ浸かっている人にこそLISPのそういう部分がアピールするのではないかと思う。

2010-07-22 Thursday

関数型プログラミング.NET開発者向け概要」という記事

 Visual Studioスタートページに表示されるMSDNの記事一覧をときどき眺め読んでみるのだが、今日読んだ「関数型プログラミングの .NET 開発者向け概要」はなかなか面白かった。

 記事はVisual Studioに新たに追加された関数型言語F#の初歩を扱った記事で、それほど深い内容ではないのかもしれないが、関数型言語に固有の術語をなるべく用いずに、(同様の処理を行う)C#コード比較する形でF#の特徴を解説しており、「関数型言語を用いると、手続き型言語で起こりがちなどんな問題を回避しやすくなるのだろう?」と以前から思っていた僕にとって興味深い記事だった。

 ちなみに、僕がこの記事を読んで感じたのは、

  • 変数の値を変更できないとしたら、もの凄く使いづらそうだ」と思っていたが、考えてみれば、Visual BasicやVisual C#文字列Stringだって値を変更できない(しかし、「文字列の値は変更できないから、もの凄く使いづらい」と思ったことはない)。
  • 「暗黙の依存関係」がマズいのであって、「依存関係」そのものが悪いわけではない(そもそも、何の依存関係もないようなプログラムは何もしないはず…)。依存関係を「明示的に」記述すればよい。
  • その際、処理の下請け、孫請けの階層構造をカッコの入れ子として表現するのではなく、ドット記法でつなげていくと、Rubyっぽくなる。

といったところだろうか。1つの記事からこんな風に複数のポイントに気づかされることなんて滅多にないので、ちょっと興奮している。F#やってみたいなー(Visual F# 2010 Expressってものが用意されていないのが残念…)。

2010-07-18 Sunday

銀行丸め

 Visual Basic 2008 Express Editionを使ってプログラミングしていて、些細なところで落とし穴にハマッた。CInt()の「銀行丸め」というヤツだ(おそらくVisual Basic 2008だけでなく、Visual Studio 2008、Visual Studio 2010の他の言語C++C#F#、J++)を用いても同様だろうと思う。また、Javaもある種のクラスのメソッドでは「銀行丸め」を行うようだ)。

 CInt()は、実数引数にとり整数を返すメソッドだが、単に切り捨てた値を返すのではなく、四捨五入に近い処理をした整数を返す。この「四捨五入に近い処理」というのがヤッカイで、小数点以下が「.5」ピッタリだった場合、「最も近い偶数整数」を返す。

 つまり、

CInt(-9.5) = -10

CInt(-8.5) = -8

CInt(-7.5) = -8

CInt(-6.5) = -6

CInt(-5.5) = -6

CInt(-4.5) = -4

CInt(-3.5) = -4

CInt(-2.5) = -2

CInt(-1.5) = -2

CInt(-0.5) = 0

CInt(0.5) = 0

CInt(1.5) = 2

CInt(2.5) = 2

CInt(3.5) = 4

CInt(4.5) = 4

CInt(5.5) = 6

CInt(6.5) = 6

CInt(7.5) = 8

CInt(8.5) = 8

CInt(9.5) = 10

 となる。

 ちなみに、CInt()する前にInt()で切捨てを行うことにより、小数点以下を切り捨てた整数を得ることができる…、と思ったら大間違い! 正の数はいいが、負の数は違う。

CInt(Int(-9.5)) = -10

CInt(Int(-8.5)) = -9

CInt(Int(-7.5)) = -8

CInt(Int(-6.5)) = -7

CInt(Int(-5.5)) = -6

CInt(Int(-4.5)) = -5

CInt(Int(-3.5)) = -4

CInt(Int(-2.5)) = -3

CInt(Int(-1.5)) = -2

CInt(Int(-0.5)) = -1

CInt(Int(0.5)) = 0

CInt(Int(1.5)) = 1

CInt(Int(2.5)) = 2

CInt(Int(3.5)) = 3

CInt(Int(4.5)) = 4

CInt(Int(5.5)) = 5

CInt(Int(6.5)) = 6

CInt(Int(7.5)) = 7

CInt(Int(8.5)) = 8

CInt(Int(9.5)) = 9

 そこで、Int()の代わりにFix()を使うと…、

CInt(Fix(-9.5)) = -9

CInt(Fix(-8.5)) = -8

CInt(Fix(-7.5)) = -7

CInt(Fix(-6.5)) = -6

CInt(Fix(-5.5)) = -5

CInt(Fix(-4.5)) = -4

CInt(Fix(-3.5)) = -3

CInt(Fix(-2.5)) = -2

CInt(Fix(-1.5)) = -1

CInt(Fix(-0.5)) = 0

CInt(Fix(0.5)) = 0

CInt(Fix(1.5)) = 1

CInt(Fix(2.5)) = 2

CInt(Fix(3.5)) = 3

CInt(Fix(4.5)) = 4

CInt(Fix(5.5)) = 5

CInt(Fix(6.5)) = 6

CInt(Fix(7.5)) = 7

CInt(Fix(8.5)) = 8

CInt(Fix(9.5)) = 9

 僕みたいな素人はこういうところでハマッちゃうんだよな。

2010-07-13 Tuesday

何だか急にシミジミと「英語勉強をしておいて良かった」と思った。

 アメリカ本家Amazon.comから英語メールが届いていた。件名は「Review your recent purchase at Amazon.com」。先月購入した腕時計レビューを投稿しないか、という内容だ。

Thank you for your recent purchase from Amazon.com.

We invite you to submit a review for the product you purchased or share an image that would benefit other customers. Your input will help customers choose the best products on Amazon.com.

It's easy to submit a review--just click the Review this product button next to the product.

 度胸がないせいもあって英会話はまるきりダメな僕だけど、この程度の文章であれば読むのに苦はない。何だか急にシミジミと「英語勉強をしておいて良かった」と思った。英語だからとビビる必要はまるでなくて、よく見てみれば中学レベル英語。このくらいをスラスラ読めないようでは…、やっぱり世界が狭まっちゃうと思うんだよな。

 ところで僕がこういう英語を読めるようになったのは、恥ずかしながら大学院に進んでからだと思う(「中学レベル」と言いながら…)。大学院では英語で書かれた論文を読む必要があった。それで初めて、英語勉強として英文を読むのではなく、書かれている内容を理解するために英文を読んだ。あの経験が大きいのだと思う。

 そういう意味では、「英語勉強」をしていても英語を読めるようにはならないのかもしれない。英語を用いて実際にコミュニケーションしてみる(僕の場合は、紙に印刷された文章を読むという一方向的なコミュニケーションだったが)ということが重要なのではないかと思う。

2010-07-04 Sunday

Gaucheの記事を読んでRubyの理解を深める…。

 月刊誌日経ソフトウエア」で2009年7月号〜2010年6月号の1年間に渡り関数型言語Gaucheの記事が連載されていた(kikaineko氏による「魔法言葉 関数型言語を学ぼう」)。

 Gauche日本人ハッカー川合史朗氏の手によるScheme処理系で、SchemeLisp方言の1つ。関数型言語には以前から興味があったのだが(今ならF#とか…)、ビビッて手を出せずにいた。それが最近、フと思いついてこの連載をまとめて読んでみた。

 連載内容は、前置記法ポーランド記法)やリスト(というデータ構造)を軽く紹介するところから始まり、主に「再帰」と「高階関数」に焦点を当てた内容となっていた(もちろん、「高階関数」の後には「ラムダ」についても解説されていた)。

 面白かった。関数型言語というものを全く知らなかったので、純粋知的好奇心を満たされた、ということもあるのだけど(例えば、「木構造」みたいなデータリストであればごく自然記述できることに驚いた)、手続き型言語なら寝惚けていても書けそうな処理でも関数型言語では全く異なる発想を求められるようなところが特に面白かった。

 「ないものねだり」傾向の強い僕としては、更にもう一歩、「手続き型言語関数型言語の背後にある計算モデルの違いがどういう発想に基づいているのか」「その違いが言語仕様にどのように表れているのか」といったやや概念的な話にまで踏み込んで欲しかったが、そうでなくとも充分面白かった。

 それに、連載を読んでいてむしろビンビン感じたのはRuby関数型言語としての側面。以前からRubyには興味をもっていて、入門書を何度か読みかけているのだけど、Rubyを単に「オブジェクト指向スクリプト言語」みたいに捉えていると、いつも途中で、これまで読んだBasicやC、Javaの入門書には決して感じられない匂いを感じ、「これっていったい何だろう? UNIXスクリプト言語Perlだとか、sedだのawkだのTcl/Tkだの…)に特有の匂いなのだろうか?」とモヤモヤした気分になってしまっていたのだ。それがこの連載を読んで関数型言語に由来するものなのだとわかってスッキリした(例えば、Ruby配列は本当に柔軟で「何でも配列に突っ込める」のだけれど、それはLispの「何でもリストに突っ込める」というところから受け継いでいるのだろうと思う。Lisp欠点は何重にも入れ子になったカッコの構造が直感的に把握しづらいことだと思うのだけど、それをRubyではオブジェクト指向の「ドット記法」で解決してしまったのだと思う)。

 関数型言語というものを知って、副作用的にRubyの理解が進みそうな予感(「副作用がない」のが純粋関数型言語の特徴のはずだけど…(笑))。

 「日経ソフトウエア」でkikaineko氏がGaucheの連載を書く前にやっていたのがRubyの連載(「Rubyをめぐる冒険2008年7月号〜2009年6月号。2009年11月号の特別付録として全12回分がまとめられている)。あれもう1回読んでみようかな!


※ 「魔法言葉 関数型言語を学ぼう」自体も特別付録として1冊にまとめて欲しい! 是非是非!

2010-04-11 Sunday

ここ1週間ほどC/C++入門をパラパラ眺めていた。

 3月末に10日間ブッ続けで勉強会を行う「狂気のVB合宿」に参加してプログラミング学習熱に火がついてしまい、ここ1週間ほどC/C++入門をパラパラ眺めていた。

 実は僕は、C入門なら過去に何度も読んだことがあるが、C++入門はほとんど読んだことがない(しかも、読んだとしてもC++の「C」部分しか読んだことがなかった。「++」部分で言うと、printfやscanfの代わりにcoutやcinを使うとか、char[]の代わりにstringを使うとか、その程度)。

 で、C++の「++」部分を学びながら思ったのは、C++JavaC#と比べて(よく言われているように)確かに面倒臭いが、Cの知識を既に持っているとしたら、JavaC#を一から学ぶよりもオブジェクト指向プログラミングというものを理解しやすいだろう、ということ。プログラミング言語としては後発のJavaC#の方が言語仕様そのものはスッキリしていて学びやすいと思うのだが、Cの土台の上にC++の皮を被せた方がオブジェクト指向プログラミング概念的理解も容易かもしれない。

 Cプログラマの強みはやはりCという比較的「低級」な言語を使っていたことでハードウェア寄りの感覚が身についている点。僕にとってオブジェクト指向プログラミングを理解するのは本当に難しかったが、その難しさの一端は「あるコードハードウェア上でどのように実行されているのか想像できない」というところにもあった(これは「オブジェクト指向概念的に理解できない」というのとはまた別の話だが)。

 例えば、「オブジェクト指向プログラミング言語には『多態性』と呼ばれる仕組みが備わっています。これは、基底クラスの型で宣言した変数派生クラスインスタンスを代入し、ある(仮想)メソッドを呼んだ場合派生クラスのメソッドが実行される、という仕組みです」と説明されるよりも、「基底クラスの型で宣言した変数(実はポインタ)には派生クラスインスタンス(のメモリアドレス)を代入することができます。そのため、あるメソッドを呼ぶと派生クラスのメソッドが実行されます。これを利用して、(抽象的には同じ機能である同名のメソッドを呼ぶだけで)実際に代入されているインスタンスの種類に応じて異なるメソッドが実行される『多態性』という仕組みが実現されています。そのためプログラマは、個々の派生クラスの違いにとらわれることなく、抽象度の高いレベルでのプログラミングに集中することができます」と説明された方が僕にはピンとくる。

 もちろん、「オブジェクト指向プログラミングとは何か」を概念的に理解することと、「オブジェクト指向プログラミング言語に備わっている様々な機能は具体的にどのような仕組みで実現されているのか」を理解することでは、理解すべきものが違うし、僕にとって本当に難しかったのは「どう書けばどうなるか」ではなく、むしろ「その仕組みは何のためにあるのか(それがどう便利なのか)」を理解することだったのだが、Cの知識に付け足す形でオブジェクト指向的な機能に関する知識を追加し、そこから概念的・抽象的な理解につなげる、という途もあったのだ、と今なら思う。

 開発の現場ではC++開発経験者がやはり重宝されているらしい。C++スターは(ヤッカイな言語を使ってきた結果)OSの働きに関してかなり深いところまでの知識を持っており、それがC++を使わないような現場でも役に立つらしいのだ。その点、最初からC#みたいな人は敵わないらしい(「最初からC#」なんて人は若い人だろうから、経験年数の差かもしれないが…)。

 まぁしかし、僕は今さらC/C++をもう一度一から学び直そうという気にはならないなぁ…。やっぱ面倒臭い。

2009-08-24 Monday

音声と表記

 考えてみると、僕はこれまで英語の発音というものを聴いたことがなかったんだなぁと思う。

 数年前に韓国語勉強を始めたときに驚いたのは、どんな入門書にも音声CD付録でついていることだった。僕は基本的に世の中の動向と無関係に生きている人間なので、現在語学書にはネイティブスピーカーによる発音を収めた音声CDがついていて当然、ということを知らなかったのだ。

 韓国語の音は全く知らなかったので、一生懸命CDに耳を傾けた。日本で売られている韓国語入門の男性ナレーションでは、イ・ホンボクさんという方が活躍している(ただし、彼はアナウンサー声優ではなく、本来は朝鮮語研究者なのだが)。この人の声を何度も何度も聴いているうちに単純接触効果が生じ、声そのものを好きになってしまった(というか、もうイ・ホンボクさん自体が好き)。いい声なんだよね〜、これがまた。

 韓国語の発音を比較的熱心に勉強せざるを得なかったのは、ハングルという文字を見ても、対応する音が全く想像できなかったからだ(何ヶ月か勉強していたら、あるとき急に、ハングルを構成する記号(「字母」という)そのものが音を発しているように感じるようになったが)。逆に言うと、カタカナでルビが振ってあったり、アルファベット表記されていたら、あまり熱心に発音の練習をしなかったかもしれない。同じことは英語にも言えるはずで、これまでネイティブスピーカーの発音で英語の単語を学ぼうと思ったことがなかったのは、単語の綴りを見ればある程度発音の想像がつくからだったのではないかと思う。

 例えば、「fitting」という形容詞がある。「fitする」という意味で、まぁ発音は「フィッティング」だろうな、と思ってしまう。ところが、前にも書いたように僕にはtの音はラ行の音に聴こえる傾向があるので、「フィッティング」というよりは「フィリング」に聴こえる。パッと聴くと、「feeling」かな?と思ってしまうのだ。

 そのため、

Chocolates and flowers are fitting presents for Valentine's day.

 というような、文字で読めば何の疑問もわかないような文章でも、耳で聴くと意味がわからないのである。僕には、

Chocolates, flowers, feeling, presents, Valentine's day

 あたりが耳に残っているわけで、チョコレートフラワーっていうとヴァレンタインズデーって感じだよね、ってな意味かなぁ、などと考えることになってしまう(別に間違ってないんじゃないかという気もするが)。

 僕の場合、英語を聴いていて多少単語がわかっても、文脈が全くわからない、ということが多い。また文脈がわからないから、単語も聴き取れない。こないだ面白かったのはMT cansで、MT缶って何だ? と思っていたら、empty cansだった(途中で、どうもゴミ拾いの話らしいと気づいて、ようやくわかった)。

 最近日本英語教育も変わってきて、文字から入るのではなくまず音から入る、というような方針らしい。日本人先生でいいんだろうかと思わないでもないが(ネイティブスピーカーアシスタント(ALT)がいるのかもしれない)、音も聴かずにローマ字読みする癖がついてしまう前に、音と表記を対応させていく(それにはかなり時間がかかるだろうが)というのは、長期的に見れば効果あるだろうな、と思う。

2009-08-20 Thursday

多様性の中に区別を立てる、ということ

 日本語の「ん」も発音記号で書くと3種類あって、日本語ネイティブスピーカー意識せずにちゃんと使い分けている。しかし、日本語ではこれらは同じ音として概念化されており、同じ文字で表記される。中国語韓国語ではこれらは異なる音として概念化されており、ピンイン中国ローマ字)やハングルでは異なる表記をされる。日本語では何故区別せず、中国語韓国語では何故区別するのか。

 まず、「ん」に3種類ある(「m」「n」「ng」)というのは、人間発声器官の生物学構造による必然的な結果なのだろう。日本語話者がそれらを意識はしないにしてもちゃんと発音し分けているのには、生物学的な必然性がある(要するに、発音しやすい音が選ばれている)。例えば、「あんぱん」の 2番目の「ん」は「m」だろうが、これは次に来る「ぱ」を発するためには一度唇を閉じる必要があり、閉じれば必然的に「ん」は「m」の音になってしまう、「まんが」の「ん」は次の「が」を発音するためには口を閉じるわけにはいかず、また舌を口の中のどこにもつけるわけにもいかず、結果として「ん」は「ng」の音になってしまう。これは、日本人でも中国人でも韓国人でも、日本語としての「あんぱん」や「まんが」を発音するときには、そう発音するのがおそらく最も発音しやすい。

 では、「ん」を中国語韓国語では異なる音として区別するのに、日本語では区別しないのは何故か。中国語韓国語ではこれらを区別しないと何か不都合が起こるのか。これについては、本当は不都合は何もないのだろうと思う。区別しないと何か不都合が起こるから区別しなければならないというわけではなく、本来、人間言語で用いられる母音や子音に関して、どんな音とどんな音を同じ音と見なすか、異なる音と見なすかには、どうしてもそうでなければならないという必然的な理由はないのではないかと思う。

 例えば朝鮮語では、強く息を吐き出す「パ」、全く息を吐き出さない「パ」、普通の「パ」を3つの異なる音と見なすが、普通の「パ」と普通の「バ」は同じ音と見なす(ただし、区別はしないけれども、実際は「パ」と「バ」を場合によって言い分けている)。つまり、朝鮮語では、吐く息の強さという次元で子音の区別をするのに対して、いわゆる清音・濁音の次元では子音を区別しない。もちろん日本語では逆で、清濁の区別をして吐く息の強さでの区別はしない。人間の発することのできる母音や子音は生物学的な制約の元でそれなりに多様だと思うが、そこに何らかの区別を立てようとするときに用いることのできる次元は様々あって、どれを用いるかについては比較的自由(もちろんこれは個々の話者が恣意的に選べるという意味ではない)なのだろう。

 それでは、何故、中国語韓国語では吐く息の強さという次元が用いられ、日本語では清濁という次元が用いられることになってしまったのか、というと、(急に曖昧な言い方になってしまうが)おそらく言語同士の類縁関係(インド・ヨーロッパ語族だとか)や、隣接地域や交流のあった他民族言語の影響、等の、社会・文化・歴史的な要因の積み重ねによって、長期的にそれぞれの言語体系ができあがってきた、ということなのだろう。

2009-08-16 Sunday

acrossとclose

 英語教材に含まれていた「英語力測定テスト」というのをやってみた。

 で…、リスニング問題で面白い間違いをした。旅行者に博物館への行き方を説明している場面で、

 It's across from the bookstore.

 (本屋の向かいです。)

 というのを、

 It's close from the bookstore.

 (本屋の近くです。)

 だと思ってしまったのだ。

 今のところ僕には、acrossとcloseを聴き分けることはできないし(もっと難しいのは、acrossとcrossを聴き分けること!)、近い将来に聴き分けられるようになるとも思えない。そうなると、どうやって博物館の位置を知るかというと、もしそれがcloseなら、close fromではなくてclose toと言うのではないか、とか、博物館本屋の隣にあるのだったらnext toと言うのではないか、とか、勘を働かせられるようになるしかない(acrossとcrossだったら、そもそも品詞が違うのだから、文章の同じ位置に現れるはずがない、とか)。個々の単語が聴き取れないのなら、セットで使われる単語の組をセットのまま憶えてしまえばいいのである。

 ちなみに、上記テストにおいて、

 In the end

 を

 Indians

 と聴き間違える、というもっと凄いミスもした(自分たちの生活環境を守る、という話だったので、文脈上、ネイティブアメリカンの話になってもおかしくはなかった)。にも関わらず、問題には正答していた、というのも謎…。