表1  LAMP<BR>Webアプリケーションを構築する際に,利用されることの多いオープンソース・ソフトウェアの組み合わせ。それぞれの頭文字を並べて呼ぶことが多い。
表1 LAMP<BR>Webアプリケーションを構築する際に,利用されることの多いオープンソース・ソフトウェアの組み合わせ。それぞれの頭文字を並べて呼ぶことが多い。
[画像のクリックで拡大表示]
リスト1  静的型の言語で書いたソースコード&lt;BR&gt;Javaで記述した。int型の変数aと,String型の変数sを加算しようとすると,コンパイル時にエラーとなる。
リスト1 静的型の言語で書いたソースコード<BR>Javaで記述した。int型の変数aと,String型の変数sを加算しようとすると,コンパイル時にエラーとなる。
[画像のクリックで拡大表示]
リスト2  動的型の言語で書いたソースコード&lt;BR&gt;Rubyで記述した。ソースコードで変数の型を宣言していないが,実行時にきちんと型整合性をチェックする。数値と文字列を加算しようとすると,エラーが出る。
リスト2 動的型の言語で書いたソースコード<BR>Rubyで記述した。ソースコードで変数の型を宣言していないが,実行時にきちんと型整合性をチェックする。数値と文字列を加算しようとすると,エラーが出る。
[画像のクリックで拡大表示]
表2  型システムの分類
表2 型システムの分類
[画像のクリックで拡大表示]
リスト3  動的で弱い型の言語の例&lt;BR&gt;テキスト処理などで使われるAWKのソースコード。1という整数が格納された変数aと,文字列“hello”が格納された変数sとを加算してもエラーは発生しない。変数sは数値を含まないため0と見なされ,1が印字される。
リスト3 動的で弱い型の言語の例<BR>テキスト処理などで使われるAWKのソースコード。1という整数が格納された変数aと,文字列“hello”が格納された変数sとを加算してもエラーは発生しない。変数sは数値を含まないため0と見なされ,1が印字される。
[画像のクリックで拡大表示]

プログラムを実行して初めて決まる事項が多い「動的言語」。柔軟性が高い,簡潔な表現が可能など複数の利点を持っている。さらに性能の問題などの欠点がコンピューティング環境の変化で目立たなくなってきた。速く柔軟な開発が求められる中で動的言語の存在感は増すばかりである。(本誌)

 LAMP(Linux,Apache,MySQL,Perl/ Python/PHP)という言葉(表1[拡大表示])が注目されています。オープンソース・ソフトウェアを利用したソリューション構築を意味する造語ですが,プログラミング言語の代表として挙げられているのはどれも動的言語です。

 以前は,企業システムをPerlやPHPのようなインタプリタ言語を用いて実装するなど考えられないことでした。昔からプログラミングの主流といえば,古くはFORTRANやCOBOL,最近ではC,C++,Javaなどの静的プログラミング言語によるものでした。しかし,今や状況は確実に変わりつつあります。

 本記事では,現在注目を集めつつある動的言語とはいったいどんな性質を持つ言語なのか,そして既存の静的言語と比較してどのようなメリット/デメリットがあるのかを考えます。また,動的言語の台頭を許したコンピューティング環境の変化についても考えてみましょう。本記事が動的言語に対するみなさんの心理的抵抗を減らし,将来主流となる,いや既に主流となりつつある動的言語へのスムーズな移行のお手伝いができることを望んでいます。

実行して初めて決まる性質が多い

 動的言語(Dynamic Language)とは,文字通り「動的(Dynamic)」な性質を持つプログラミング言語です。動的の反対語である「静的(Static)」と対比してみると,その性質が分かりやすいかもしれません。

 静的な性質は,プログラムを実行していない状態で決まる性質です。例えばソースコードだけで一意に決まるような性質は静的です。プログラムのうち静的な部分とは,変数や手続きの名前と型,制御構造の構成などです。これに対して動的な性質は,プログラムを動かしてみて初めて決定する性質を意味します。変数などの具体的な値,実行時間,使用メモリー量などが動的な部分に当たります。

 もちろん,プログラムが採用しているアルゴリズムと入力される値が分かれば,実行しなくても出力が分かる場合もあります。ただ現実には,そのような単純なケースはほとんどありません。プログラムというものはそもそも実行してみないと結果が分からないような処理をするためのものですから,あらゆるプログラムは程度の差こそあれ動的な性質があることになります。ですから,厳密に言えば静的と動的の境界線はあいまいです。特にオブジェクト指向プログラミングは本質的に動的ですから,すべてのオブジェクト指向言語はある程度動的な性質を備えています。こうしたことを踏まえると,動的言語とは数あるプログラミング言語の中でも,動的に決定する性質が多い言語であると定義できそうです。

 最近になって広く注目を浴びるようになった動的言語ですが,その歴史は意外に古く,最古の動的言語と呼ばれるLispが誕生したのはCOBOLよりも早い1958年です。そこからSmall-talk,Perl,Python,そして私自身が設計・開発したRubyにいたるまで,動的言語の歴史は連綿と続いてきました。

 さて,「動的に決定する性質が多い」と一言で言っても,具体的にどのような性質があるのかが分からなければ,動的言語の良さを理解するのは難しいでしょう。動的言語の多くが共通して持っている機能について紹介し,それがどのように優れているかを見てみます。

動的言語では型を宣言しない

 動的言語に特徴的な性質として,変数や式に型情報を付けない(オプションとして付けることができるものはある)ことがあります。動的型と呼ばれるものです。これを「型がない」とか「弱い型」と呼ぶ人もいますが,明らかに間違いです。動的型とは「型がない」ことではなく,プログラムの字面に型情報が登場しないということです。

 実際のコードを見ながら,「静的型」と「動的型」を比較してみます。静的型を持つ言語の代表として,Javaを用います(リスト1[拡大表示])。まさに例題のための例題といった感じのつまらないプログラムですが,ここからいくつかのことが分かります。

* すべての変数には型の宣言を付けなければならない
* すべての手続きは引数と戻り値の型を宣言しなければならない
* 結果として式の型はコンパイル時に分かる
* 型が合わない演算はエラーになる

 こうした性質を持つ型システムが静的型です。静的型はJavaをはじめC++など主要な言語の多くが採用していますから,みなさんにとってもなじみが深いでしょう。

 一方,動的型を持つ言語のコードはリスト2[拡大表示]のようになります。動的型の言語の代表例として筆者がもっとも親しんでいる言語であるRubyを用いています。Javaのコードと比べると,ずいぶん簡単です。10行必要だったものが6行で記述できていますから,単純計算して40%の削減になります。空白などを除いた文字数で比較すると,Javaが157文字なのに対してわずか42文字です。実に,70%の削減です。

 ただ,ここで強調したいのは単にプログラムが簡潔になったことではありません(もちろん簡潔さも大切ですが,これについては後述します)。それ以外に,動的型システムは次のような重要な特徴を持っています。

* 変数や式に型を宣言しない(Rubyでは変数宣言そのものがない)
* プログラムの字面からは型が分からない
* データが型情報を持っているので型の不整合は実行時にエラーとなる

 つまり,動的型システムではデータ自身が型情報を持っています。型チェックはきちんと実行されますが,プログラム上はそれを表記しないので,コンパイル時ではなく実行時にチェックされるのです。

動的/静的と強い/弱いは別の軸

 このように,プログラムの字面から型の不整合が発見できるかどうかで「静的/動的」の分類ができます。これに加えて型システムの分類には,型の不整合がプログラムによって発見できるかどうかで決まる「強い/弱い」という軸があります(表2[拡大表示])。

 例えば,Javaのような言語は「静的で強い」型システムを持つ言語です。変数や式に型があり,型の不整合がコンパイル時に発見できるからです。一方,CやC++は「静的で弱い」型を持つ言語とされます。変数や式に型はあるものの,キャスト(型変換)の仕組みを用意するなど型システムに抜け穴があり,すべての型エラーを検出できないためです。ただし,ここでいう「強い/弱い」ははっきり線を引けるようなものでなく,段階的なものです。例えば抜け道があるC++はJavaよりは弱い型システムを持ちますが,ほとんどの場合にはきちんと型の不整合を検出してくれます。

 動的な型の言語にも,強い/弱いの区別は存在します。プログラムには型情報は含まれないものの,データ自身が型についての情報を持ち,実行時に型の不整合がきちんと検出できるものは「動的で強い」型システムです。Lisp,Python,Rubyなどがこれに当たります。PerlやPHPは「動的で強い型」と「動的で弱い型」の両方の性質が混在しています。

 「動的で弱い型」には,AWKのようにデータが混在したときに処理系が適当に解釈してしまうものと,アセンブラやBCPLのようにデータの解釈がプログラマに任されているものがあります。前者は,たとえ型の不整合があっても処理系が“親切な”データ変換をするため,型エラーは検出できません(リスト3[拡大表示])。プログラム本体はリスト2におけるRubyのものとまったく同じですが,整数と文字列の加算が何のエラーも起こさないことに注目してください。AWKは+演算子の両辺は数値であると見なし,“hello”は数字を含まないのでゼロと解釈します。1と0を加えると1なので,1を印字したというわけです。

 この自動変換機能は一見便利そうですが,間違いの検出が遅れるので害の方が大きいのです。Perlもこの弱い型を備えていますが,新しいバージョンでは一種の型宣言を加えることにより,エラーを検出しやすくしています。Rubyもごく初期のバージョンではこの「弱い型」機能がありましたが,弊害の大きさを考えて早い時期に取り除きました。

 強いか弱いかに触れずただ単に「動的な型」と呼んだとき,たいていの場合は「動的で強い」型を指します。プログラムの字面から型を判断できないことに惑わされ,実行時にきちんと型不整合エラーが検出できるにもかかわらず「弱い型」とか「型がない」と呼ぶのは間違いです。「型がない」という悪口(?)にふさわしいのは「動的で弱い型」ですが,今ではそれは少数派になっています。

 一方,プログラムの字面どころかまったく型情報を備えない言語も存在します。究極の弱い型ですね。例えば,アセンブラやBCPLではすべてのデータは数値です。それを整数と見なすか,アドレスと見なすか,文字コードと見なすか,といったことはプログラマの裁量に任されています。プログラマは変数名などからその値の「意味」を見いだし,それにふさわしい取り扱いをすることを求められます。間違えばプログラムが異常終了するだけです。完全な自己責任が求められていますね。このような型システムこそが「型なし」と呼ばれるにふさわしいと言えます。

 なお,C言語も型なし言語の影響を受けています。Cには型がありますが,数値からのキャストや加減算可能といったポインタの取り扱いには,アセンブラに近い性質が見られます。Cはしばしば「高級アセンブラ」と呼ばれますし,直接の先祖にはやはり型なしであったBCPLがいますから,無理からぬことかもしれません。


まつもとゆきひろ Yukihiro Matsumoto/ネットワーク応用通信研究所 主任研究員

1965年生まれ。鳥取県米子市出身。筑波大学第三学群情報学類卒業。高校時代からのプログラミング言語おたく,オブジェクト指向おたく。1993年からオブジェクト指向スクリプト言語Rubyを開発中。古今東西のプログラミング言語の「良いとこ取り」の性質から海外でも人気上昇中。1997年から株式会社ネットワーク応用通信研究所 主任研究員という立場でRubyの開発をメインの仕事としている。メールアドレスはmatz@ruby-lang.org