TOP > プログラマ2.0日報 > 2008年11月17日

あすなろBlogger

facebookに投稿 このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク このエントリーをはてなブックマークに追加 この記事をクリップ! livedoorclip ユーザー数 BuzzurlにブックマークBuzzurlにブックマーク この記事をtweetする

プログラミング文章読本~手続的ではなく宣言的に

2008.11.17

さて、前回「叙述性」という評価基準がある...という話をしたのですが、こういう「叙述性」というのは、実際考えてみると、深くプログラムの「宣言性」というものと関わってきます。私はですね、

プログラムは手続的(あるいは命令的)であるよりも、宣言的である方が、ずっと管理をしやすいものだ

ということを自身のプログラミングの中で「自分の信条」としているところがあります。今回はこういうお話です(細かく言うと(Wikipedia)の第1の定義の方です)。

前回の例で言えば、

// コード1
root.add( kodomo1.add( mago1.add( himago1,
                                  himago2 ),
                       mago2.add( himago3 ),
                       mago3 ),
          kodomo2.add( mago4.add( himago4 ),
                       mago5 ) );


というプログラムと、それと同等な

// コード2
root.add( kodomo1);

root.add( kodomo2 );
kodomo1.add( mago1 );
kodomo1.add( mago2 );
kodomo1.add( mago3 );
mago1.add( himago1 );
....

とを比較した時、どちらが判りやすいでしょうか?? まあこれは言うまでもないでしょう。 この違いは、

コード1
root という変数が「どういう構造であるか(what)」を記述している
コード2
root という変数の構造を「どう作るか(how)」を記述している

と言えます。要するにこれが「宣言的なプログラム」と「手続的なプログラム」の違いだと言えます。宣言的なプログラムは「それが何であるか」を記述しますが、手続的なプログラムは「それがどう動くか」を記述する...と理解するといいのかな? この時、手続的なプログラムは大きな弱点を抱えることになります....それは

時系列

という問題ですね。今の例では順番は関係ありませんが、手続的なプログラムでは、「実行の順番」が大きな問題になります。それに対して、宣言的なプログラムでは、

それが何なのかが重要なので、どういう順番で作ろうとも、最終的な結果が記述に合致している限りどうでもいい

ということになるわけです...要するに、宣言的なプログラムでは「構築の順番」は舞台裏に回るように、うまくインターフェイスを設計することになります。たとえば何かをさせるために、決まった順番でインターフェイスを呼ばなければならないような(手続き的な)ライブラリは使いづらいに決まってます。たとえ1つインターフェイスを増やすことになっても、「セットされたオプションから内部的な状態を作り上げる」ための専用のインターフェイスを作って、「○○をセットするのが最後で、これによって最終的に内部状態が作り上げられる」というような、「時系列についての暗黙の使い方」が利用コンテキストに含まれない方がいいに決まっているわけです(たとえば Haskell だと遅延評価しますから、「関数を呼んだ順」が一般に処理の順番に反映しません....まあ Haskell は過激ですけどね)。

言い換えると、特にOOPの場合は、

プログラムが「何をするのか」を順を追って記述するよりも、そのオブジェクトが「何なのか」を宣言的に記述すべきだ

ということになり、これは実際にはOOPの精神とも合致するわけです。オブジェクトが備えるべきインターフェイスが、このオブジェクトが「何である」のかを決定し、それを「オブジェクトの仕様」として記述していく....これがオブジェクト指向であり宣言的であるプログラムのあり方なのでしょう。

実はこれはですね、「プログラミング言語」というものの性格にも一致する、と私は考えています。最近ではあまり意識しないといえばそうですが、高級言語でのプログラムというのは、

書いたとおりに動く、というものではない

という性格を持っているわけです。これは勿論、高級言語のモデルがいくつ変数があってもかまわない「ランダムアクセス機械」であるのに対して、実際のCPUは固定された数のレジスタがあって、そのレジスタでしか計算ができなかったりする「レジスタ機械」である、というモデルの微妙な違いがあり、そのために、

高級言語のモデル → CPUのモデル

へ変換をする作業がコンパイル(翻訳)と呼ばれるわけです....この時、いくつ変数があってもいい「ランダムアクセス機械での記述」から「レジスタを使って計算するための記述」への変換がなされ、この時に、

そのレジスタ機械での合理的な計算の仕方

への舞台裏での変換が「最適化」と呼ばれるわけです....ですから、私たちが高級言語で書いたプログラム、というのも

実際に動く機械語コードを作るための(場合によっては大雑把な)仕様

を与えている、と言えばその通りなのですね。ですから、

そもそも高級言語で書く、ということ自体が宣言的であり、本当に手続的に書くのならばアセンブリで書くしかない

と言っても過言ではないのかもしれません。

宣言的プログラミング

という書き方は必ずしも関数型言語だけの問題ではなく、日々の実践の問題でもあるのです....

投稿者 : 杉浦 こずえ | 投稿日時 : 2008.11.17 09:16

カレンダー

<< 2008年11月 >>

            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            

最新のエントリー

最新のトラックバック

最新のコメント

Tag

バックナンバー