What is it, naokirin?

プログラミング言語の難しさとは(いろんな言語に触れてみてほしいと思って考えてみたこと)

最近友人と話していると思うのは、人によって言語やパラダイムに対しての価値観や捉え方がかなり違っていることです。

私はどの言語も使いこなせるほどの能力はないですし、ちょっとしたプログラムを書いたことしかないような言語もたくさんあります。
ただ自分が今の時点で感じたことや考えを残しておきたいので、ここで書いておこうと思います。間違いもあると思いますし、本質でないこともあると思います。それに自分の価値観に基づいた私見等も入り込んでいるとは思います。価値は薄いと思いますが、それでも読むという人はご了承ください。

プログラミング言語の大別と難しさ

プログラミング言語っていろんな言語がありますよね。
よく使われている言語でいえば、C, C++, Java, C#, Visual Basic, Perl, Ruby, Python, JavaScript...

ほかにもあるとは思いますが、プログラミング言語を列挙するのはここまでにしておいて、実際にどんな言語があるでしょうか。

型システムの違い

Webアプリケーションでよく用いられている言語として、RubyPerlといった言語があげられます。これらは動的型付け言語といわれています。

一方でC、C++Java、etc. は静的型付け言語とよばれています。

これらの違いは

x = 1
x = "a"

なんてことができるかどうかという点にあります。

もちろんこれらには賛否両論あって、もし型が間違っていた際に動的型付けでは見逃されてしまう可能性が多く、また再代入も容易にできる場合は間違えて同じ名前を付けてしまっても型レベルでも判定がされないことがよくあげられています。

ただ動的型付けでは、同様の機能を持つ「実質的に」同定できるものを簡単に同じ変数で扱えること、また型に捉われずに機能重視でコードを書くことができることがあげられると思います。またプログラマの生産性が向上する(コード量が削減できる)という点が挙げられることもあります。

あとあまり知られていない、というより私があまり知らないのですが、型のない言語というのもあるようです。
関数型言語でLazy Kといった言語がそういう言語らしいのですが、実際に利用されている言語では型システムが存在しない言語はほぼないのではないかと思います。(これは主観ですので、間違いがあるかもしれません)


あと型に関していえば、強い型付けか弱い型付けかという違いもあります。
弱い型付けであるというのは、不正なキャストが起こりえるような暗黙的な型変換が存在します。たとえばC言語であれば

int main(void) {
  char x = 12;
  int y = 1;
  int z = x + y;

  return 0;
}

です。これはchar型に整数値が渡され、その後char型とint型の和がとられている訳ですが、C言語ではこれはコンパイルエラーとはならないのです。ちなみに言えば実行時にもエラーが発生することはありません。

弱い型付けでは一定のコード量の削減が可能になる一方、潜在的なエラーやデバッグ時にはいつどのような暗黙的型変換が起きるかを注意深く意識する必要が出てしまう場合も発生してしまうという欠点があります。後者であげられるような欠点は非常に大きな欠点となり得るため、最近は強い型付けであることの方が多いようです。ただし推論等により強い型付けでのデメリットを解消する試みはなされているようです。

という訳で、型システムの違いとして

があります。


ここからこの型付けの違いによる難しさというのを考えてみます。

例えば動的型付け言語が難しい(というのは記事の最初に書いた友人の一人が言っていることですが)というのは、ミスタイプが多いために型エラーによるバグ検出が欲しいということがあるそうです。たしかにそういう面は多いですし、私自身すべての領域で動的型付けがよい解だと思っている訳ではないので部分的には賛成しているところです。

一方静的型付け言語では、動的型付けほど柔軟性がなく、概念よりも型に支配的なコードになってしまいがちであることが難しいと感じさせるようです。あとは絶対に型を明示しないといけない(ものも多いために)動的型付け言語の方が楽にかける点もあるようです。ただしこの点は非常に強力な型推論のある言語も出てきたためにあまり大きな差異とは言えなくなってきたように思えます。

あとは動的型付け言語の方がコードが短くなりやすいために、コードの理解にかかる時間が短くなりやすいということもあげられるようです。

パラダイムの違い

最も言語間の差異として意識されるのが、このプログラミングパラダイムの違いではないでしょうか。

これに関しては非常に多種多様なプログラミングパラダイムがあるため、ここで語るのは正直無理があります。
という訳で、Wikipediaに投げますw
http://ja.wikipedia.org/wiki/プログラミングパラダイム
http://ja.wikipedia.org/wiki/プログラミング言語の比較

ただよく聞く言語のパラダイムとしては

があげられると思います。


特に多くの人が使っている言語として、命令型およびオブジェクト指向言語があります。
これらが浸透している理由の一つとして、「命令的で逐次的な実行が一番にあり、状態は常に容易に変更できる状態にある」ことだと思います。もちろんこれは私の考えであっていろいろな意見があると思います。
また副次的ではありますが、命令型やオブジェクト指向といった言語は非常に目に触れる確率が高く、最初に入門しやすい点があげられるのではないでしょうか。

一方で機能上使う確率が低いために使われていないことが多いパラダイムがあることもいえます。それらはおそらく使用すべき領域をイメージしにくいがために難しく感じる気がします。それから、情報が一般的に少ないこともあげられると思います。これはある種の言語を学ぶ際に私自身実感したことです。


最近、関数型言語についてよく難しいという話を聞くのですが、一つは一般的にプログラマが最初に触れると思われる命令型やオブジェクト指向といったパラダイムの言語とのギャップ、副作用がデフォルトで許容されていないこと、そして必要以上に数学的な難解性が強調されている点があるのではないかと思います。正直、モナドとか言っているときに数学の圏論を意識しながらコードを書いている人が関数型言語を使う一般のプログラマであるというような感覚は誤解だと思います。(もちろん知っていることはいいことですが、それがないと使えないという訳ではないと思います。もちろんステマです。)

目指す目的の違い

言語は上記のようなシステムの違い以外にも、目指す目的によって様々なものがあります。

たとえば基礎構文としては最低限の機能のみを提供しライブラリによって一般に必要とされる機能を提供する言語や、多くの機能を最初から提供している言語、型推論によって簡潔に書くことのできる言語等いろいろあると思います。(どこかの人間には理解不可能な言語とかもありますし)

そこでそれらの違いによる言語の実装で難しさを感じることもあると思います。

私はScalaという言語に関しては、感覚的に難しさを感じています。読みにくいとかではないのですが、単純にScalaのほかの言語にはない機能になれていない点があると思います。

「難しさ」の難しさ、それと難しいなりにやってみることの良さ

正直言って、他人の「難しい」を理解するのは非常に難しいことだと思います。それを伝えることもまた難しいです。

ただいろんな言語を学ぶことは非常に勉強になりますし、自分がメインで使っている言語でのプログラミングでも役に立つと思います。
難しいかもしれないですが、少しでも勉強してみることがいいのだと思います。

例えば関数型言語で言えば、Haskellを、モナドを触らずともよいので基礎的な部分だけでもやってみるだけでも価値はあると思います。少なくとも私は自分でそうやってみて価値があったと感じています。

もちろんもっと深く言語学習をすることがよりよいのだと思います。でも、難しいことを無理にやることがすべてではないと思ってます。ちょっとだけでも自分のやっている言語と違う世界に触れてみてはいかがでしょうか。(結局これが言いたかった。ついでに未来の自分が詰まったときにも投げかけることができればいいかなと思ってます。)

追記:
難しい意外にもプログラミング言語には宗教みたいなものも存在していて、その辺りが最も難しい部分だと思います。
何を信じて何を捨てるかは人それぞれだったりします。私はその辺りが結構幅広く大丈夫だったりしますが、その辺りも含めて人にお勧めするときには考えてみたいですね。


最後に本の紹介

おそらく最も気楽に入れる?(すみません、かじり程度しか読んだことがありません)

7つの言語 7つの世界

7つの言語 7つの世界

がっつりいろんなプログラミングの形式について学びたい人向け(正直ページ数がちょっと多いです)

コンピュータプログラミングの概念・技法・モデル (IT Architects' Archiveクラシックモダン・コンピューティング)

コンピュータプログラミングの概念・技法・モデル (IT Architects' Archiveクラシックモダン・コンピューティング)