そこそこプログラミング出来るようになった現在から、右も左もわからなかった頃、入門者時代を振り返り、なぜプログラミングは分からないのか?ということについての根本的原因を明らかにするのが本エントリの狙いです。一般的な観点(非プログラマ的観点)からの考察になります。特に具体的なコードは載せませんが、前提とする言語はC#としています。
※原稿用紙15枚分ほどで長いッ!!。
暗号だから読めない
英語を使った人工言語だから、やはり英語力はそれなりに必要なのではないか?というエントリを以前書いたことがあります。
単純な単語力以上に、英語をリアルなスピードで使える力(ちから)、タイプしていく力がより大事なのではないか?という仮説です。もちろん英語が出来なくても、プログラミングは出来るんですが、日本人にとっての大きな壁はそこにある気がします。つまり多くの日本人にとって英語は暗号みたいなもんだし、"二重の暗号"になってしまうのではないか?ということです。
で暗号というのはつまり"コード"です、プログラム・コードのコードと同じ"code"
暗号における"コード"というのは、つまり言葉の意味を入れ替える、というタイプの暗号を指します。普段使っている言葉が、違う場所では違う意味で使われているとしたら混乱しますよね?白が黒という意味だったら大変なことになってします。
しかしプログラミングでは、そんなことがたくさんあるわけです。
現実社会(リアル)とは違う意味
最も代表的な例が、" = "(イコール)でしょう。本来ならば、左辺と右辺は"等しい"という意味で、数学的事実を述べるための記号です。
a = b ; //現実社会においてはaとbは等しい、という意味だが・・・
しかし、プログラミングにおいては左辺にある"変数"に対して、左辺の"変数"の値を割り当てる、アサイン(asign)する処理を表す記号と成ります。つまり、ここではbの値をaに割り当てていることになり、aとbは等しい、という意味ではないのです。(処理の結果、等しくはなるわけですが)
もう、この時点でワケわかんないですよね?しかし、そういう決まりなんです。だから納得してください!と言われます。でも、そういう決まりなんですって言われて直ぐ納得できる人は少ないわけで。ここがプログラミング入門者にとってキツイ。
そしてこの"変数"自体も違う意味ですからね。メモリの一部分に名前をつけて、プログラム内でデータの保存に使えるように確保したものであり、数学における変数とは厳密には違います。プログラミングにおいて"変数"は何かを入れる箱のように例えられますが、そのような性質から単に"変数"という言葉を割り振られただけです。"関数"なども同じです。(コンピュータ上のモノを数学用語を使って抽象化した結果?)
何かに例えることによって、分かりにくいコンピュータ上の機構を人間に分かりやすいようにしよう!ということは多くありますが、そのたとえ話を本気にしすぎてしまうとかえって分かりにくくなってしまうのではないかと思います。
このような普段使われている言葉、記号がプログラミングにおいては違う意味、概念として使われている、というのが混乱の元です。
自然言語とプログラム言語は近づけようとはしてますが違うものです。(言語によって、どれくらい近いかは変わる。)なので、最初はその意味を理解して覚えないといけないわけですが、ダブル・シンキングが必要になります。2 + 2 = 5なのです。
テキストだからこそ想像力が必要
なので最初はその暗号の読み方、つまり文法を学んでいくことになります。しかし、ただ暗号の意味を分かるようになってもコードは読めません。なぜか?小説を読むように想像力を働かせないといけないからです。
要は表層的な記述を読んだだけではコードを読んだとはいえない、ということです。そのコードは何がしたいのか?それを実現するためにどんな手段を採用しているか?(ソリューション、アルゴリズム)を読み取らなければいけません。で他人のコードを読むことが大事とは言え、もちろん最初は文法も理解し切れてないし、そういう背後にある考えや論理を読む、ということも初心者には難しいわけです。
視覚的にプログラミングしていくソフトもあるでしょうが、基本的にはプログラム・コードはテキスト主体で、文字の集合体です。小説は文字だけですが、私達はそれを読むことで、様々な世界や物語を頭の中に思い浮かべることが出来ます。
コードも同様に単なる文字の集まりであっても、確かにコンピュータ上には何らかの世界が展開されており、なんらかの仕事がされています。それは画面に文字を映す、という具体的なものかもしれませんし、大きな仕事を達成するための細かい、人間にはよくわからない仕事かもしれません。それらを想像する力が、最初はないから読めません。
目には見えなくても、確かに存在し、直接的には人間には分かりづらいことであっても、具体的な何らかの処理をしているわけです。そのことを感じ取れるように、想像できるように知識を付けていくことが求められます。プログラミングの文法というのはあくまで書式上のルールでしかなく、逸れも大事ですが、物事の仕組みや論理的な思考の方が重要だと思います。
コンピュータと人間のギャップ
プログラミングというのは、人間が手作業でやろうとすると面倒くさい、時間がかかる、あるいは事実上不可能な仕事をやってもらうための手段です。ザックリ言ってしまえ、コンピュータの計算能力を利用して、現実世界における問題を解決するための機械への命令文を書くことがプログラミングです。
Siriみたく話してやってもらうのが理想ですが、現時点では不可能です。しかしプログラミングを始めたばかり、あるいはやったことがない人は、このことが理解できません。なぜならプログラミングという作業と普段コンピュータを使ってやっていることが、結びつかないからです。コンピュータと人間がいろんな意味でどれほどかけ離れた存在か?ということがよく分かってないから、ということになります。
昨今はディープラーニング・ブームで人工知能の熱が高まり、また先述のSiriなどもあり、どんどん人工知能が日常のものになってきつつあります。人口知能によって仕事が奪われる!のもいよいよ現実になるか?みたい話題もよく見聞きするようになりました。
そうした流れの中で見て取れるように、世間的にコンピュータは人間に相対する存在であり、超える存在だと捉えられている、と考えることが出来ます。これは、ある意味では正しいし、しかし過剰評価の部分もあります。
人間の友達、あるいは敵としての存在するコンピュータ、AIは古いSFから現代のアニメまで、よくモチーフにされます。しかし、そのようなレベルの人工知能を実現するには、まだまだ十数年の時間がかかるようです。オバマ元大統領が任期末期にGoogleの中の人からそのようなテーマについて聞いたようなので、実際そうなのでしょう。
人間は何にしても、擬人化して捉えるような部分があります。特に日本人はそこらへんの気質は強いのかもしれません。人工知能を過剰に擬人化して、人間のようにとらえてしまうのは、少なくとも現時点では、コンピュータというものへの理解を妨げます。
ではコンピュータとはどんなもので、人間とどう違うのか?
そしてコンピュータを利用するとはどういうことか?
利用に関して、たとえ話を石油による火力発電で考えてみたいと思います。火力発電は石油そのもの自体をエネルギー化するのではなく、石油を燃やして湯を沸かしてタービンを回して発電しています。実はコンピュータによる仕事もこのような転用に近いです。コンピュータの莫大な計算を計算以外(つまり電卓以外)の仕事で使う、ということで、コンピュータが主体的に何かやっているわけではないんです。
使う言葉も考え方も違う
コンピュータの言葉は0と1であり、考え方は全て計算です。これが全てであり、だとすると、やはり人間とは明らかに異なった存在であると分かります。しかし、最初はこの事実を受け入れるのは以外と難しいです。
なぜならワタシ達現代人は日々の生活の中で、当たり前にコンピュータを使いこなしている(ように思わされている)からです。あらゆることをスマフォでやっています。なので、プログラミングを学び始めて直面する様々な課題とそうした普段使っているコンピュータとのギャップがとてつもなく大きいものなっています。
Hello Worldプログラムは、普段使っているようなソフトを自分で作ってみたい!という人にとっては退屈すぎるモノです。
データ(この場合は文字列)を"入力"し、ライブラリにある標準関数を使い、"出力"するというプログラミングにおける基本的なことを短いながらに網羅しているプログラムであり、実は凄いプログラムなんですが、どうしても「なんだ!この詰まらないプログラムは!」となってしまいます。
そして、どんなコンピュータであれ全て0と1に構成され、計算によってあらゆるソフトは動いています。あんだけいろいろ出来てんじゃん!?0と1だけであんないろいろ出来るのはおかしくない?みたいに思うのが普通です。それもやはり障壁となるギャップのひとつです。プログラミングを学ぶ上では、まずそうした手軽にコンピュータを使うということと自分でプログラミングするということの落差を呑み込めるようになるのが大事なのかもしれません。
数字で表せるモノであれば、最終的にそれらは0と1だけで表すことができ、コンピュータ上で取り扱うことが出来るわけです。(10進法から2進法への変換)なにより、現代のコンピュータはアホみたいに莫大な計算力があります。一秒間に何十億回という計算が出来ます。コンピュータに暗算勝負を仕掛ける人はいないでしょう。
数字で表すことが出来て、かつ計算することが出来る問題であれば基本的にはコンピュータは解決することが出来るということになります。しかし、そうでなければ、そもそもコンピュータがそうした問題、仕事を理解することすら出来ないのです。
つまり計算によって答えが出せる問題ならば、0と1で構成された計算式による命令文をコンピュータに実行してもらうことで解決できる、ということになります。
プログラミングの目的
さて、実際のプログラミングにおいて、問題なのは数字で表す、つまりデータ化や、そうしたデータをどう組み合わせて、どう計算するか?を考えるのは人間ということです。"上手いやり方"を人間がコンピュータに教えないといけません。
(そうしなくて済むようになるかも?というのがディープ・ラーニングらしい。)
プログラミングは単にコードを書くだけでなく、そうした領域の問題解決も含むわけです。と同時に、既存のコードにはそうした部分が含まれているのであり、コードを読むということは、コードの背後にある概念を理解する、ということになります。
つまり、目の前にあるコードというのは結果の産物であり、それに至るまでには様々な工程を経ているということです。だから、コードを読むというのは難しいのです。
絵が書けます。音楽が聴けます、作れます。映像を見れます、作れます。
夢のようなことを実現するための処理をコンピュータはしてくれています。
しかし、どう処理するかの命令は人間が書いています。人間のやって欲しいことというのは、コンピュータには基本的に理解しがたいことであり、コンピュータに分かるような形で命令を書かなければいけません。
つまり、人間とコンピュータのギャップを埋める、というのがプログラミングの本質だということになります。なので、そこをまず理解することがプログラミング入門の一歩の気がしますし、それなりの時間が掛かるのかなと思います。
じゃあ、どうするべきか?
注意点と対策をまとめます。
プログラム・コードは一種の暗号であり、人間側の都合とコンピュータ側の都合が交じり合っているので、惑わされない。分かりにくくて当然と考える。
コンピュータ上でことを人間が分かりやすいように何かに例えることが多いが、あくまで例え話なので本気にしない。
コードを読むというのは、表層的に読んでも意味がなく、何がしたいか?どう解決しているか?を理解する必要があり、その分野に文法は直接的には関係ない。
むしろ、理想論的にはコードを書き始めた時点で、コンピュータにどう指示するか?という問題解決の手段は見つかっており、その解決法を文法に沿って翻訳したものがコードと呼ばれるものに過ぎない。(現実的には試行錯誤が必須。)
Hello Worldは詰まらないプログラムだけど、そこで諦めない。
やはり、それなりに時間が必要なので焦らず自分で考える力を付ける。
文法を覚えきるより、簡単なプログラムを自分で書いていく方がいい。
コンピュータと人間の違いを理解し、その差を埋めるように"お願い"するということを意識する。
あくまで個人的な見解も入ってますが、こんな感じでしょうか。
最後に
という感じで未熟者がいろいろ講釈たれたわけですが、とにかく言いたいのは、
プログラミングおもしろいから、諦めずに頑張ろうぜ!ということ。
まぁ仕事としてやってないからってこともあるのかもしれませんが、でも馴れるまでが大変だったとはいえ、単純にいろいろできるようになるとやっぱ楽しいんですよね。
もちろんプログラミングは手段であり、それを使って何をするかが大事なんですが、それ自体がおもしろいなぁって。
Unityなんかは特にプログラミングできなくてもゲーム作れるよ!という触れ込みではあるんですけど、逆にプログラミングできると何でもできますからね。なんかプログラミングをネガティブなものとして捉えるのはもったいないと思います。
いや、実際まともな動作にするには大変ではあるんですけどね。