文系人間のJava再入門0: プログラミングという行為に対する理解

# プログラミングの学習速度が本当に十人十色問題
学校の授業でJavaを習ってみたけどなんだかよくわからないという話を聞きます。プログラミング言語の初期の初期の段階でつまずいてしまう理由を日々悶々と考えた結果を改めて吐き出す記事です。
プログラミングを学びだしたけど，正直全然わからないという学生の助けになればと思います。思いのほか長い文章になってしましました。

# 私
* 英語のできない文系（専攻は哲学でした）
* 最近は[Elixir](http://elixir-lang.org/)と[Rust](https://www.rust-lang.org/en-US/)を自習中
* Javaも好き

# 趣旨
* 計算機システムがよくわからなかったり，アルゴリズムがよくわからなかったりしても，想像力で何とかしていたあの頃を思い出しながら，「こんな理解の方法があってもいいんじゃない？」とゆるく提案する。
* 文系は文系なりの方法でプログラムと向き合う

# Hello World
多くの言語のサンプルなどで最初に触れるのはこの「文字列を出力する」という処理です。なんというか，この「文字列を出力する」という表現がお堅いというか，第一印象が「なんだか高圧的な文章」だったのを覚えています。

```java
public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("Hello World");
	}
}
```

こういう感じのサンプルが巷には溢れていることと思います。

# プログラムの主体は誰なのか
Java言語に限らず，プログラミングの学習時に出会う文章は，「文字列の出力方法は以下の通りです。」や「ファイルの入出力の方法を学びます。」といった感じの主体が自分であるような文章が多いです。確かにコードを書くのは「いざ勉強しようぞ」と思っている本人です。私自身もよくこのような話し方をします。「よし，今日はちょっとBlueTooth使ってみよか！」みたいな感じです。
ですが，同時に「プログラムはコンピュータに出す指示書です。」のような文章もよく見ます。これは，プログラムを実際に動かすのはコンピュータだということを明確にするための文章です。このことから，
1. 能動的に自分がコンピュータに対する指示をプログラミング言語で書く
2. 正しく書けていれば，コンパイル時にソースファイルがクラスファイルに変換される
3. クラスファイルの記述の通りにプログラムが動く＝コンピュータが指示した通りの動作をする（思った通りに動くかは別問題）
ということになると思うのですが，案外ここが最大にして最高の溝となっているのではないかとふと思った次第。

# System.out.println(String text)
このコードでプログラムがしっくりくる人って実際どれくらいいるんでしょうか。
私が感じたのは「なんかよくわからんけど，動く凄ええええええええええ」が初めて触れたときを忠実に再現したものです。その後，多くの友人に出会い，その中で心の中でボスと思っている方が「ターミナルに文字が出たところで何もテンションが上がらなかった」と言っていました。
何かが動くことを純粋に凄いと思った私の感覚は，おもちゃが動くことに似ています。私は幼少の頃，サルが変な音を鳴らしながらシンバルを鳴らして顔を振るという行為を繰り返すおもちゃを店頭で見ているのが好きだったのですが，なんかよくわからないけど動いている（どんな動きをするかの好みはありますが）ことが，原理がわからないからこそより凄いものに思え，わくわくしたのです。でも，それは誰しも感じる感動ではなかったのでしょう。もしかしたら「動く（何かができる）」ということの程度の問題なのかもしれません。でも，ここにビビっとと来なければ，とたんに学習意欲が削がれてしまうということは想像に難くありません。ここを突破する方法が見つかれば，最初からテンションMAXでプログラミングを学べるのかなと思います。普段はできるだけ楽しく使えるものを授業のサンプルとして上げようとはしていますが，ただそれはまた別の話。今回はビビっと来ない人にどのようにプログラムってこういうものだよと伝えていくかの模索です。

# 余談：勉強を始める人は勝手に始める（勝手に進める）
こういう認識の人も割といるようです。多分これは，やってみたらビビっときたから今までずっと続けてきたっていうことだと思います。そしてそういう人はプログラムに対する学習意欲が総じて高いです。だって，もう「ビビ」って来てるんですから。問題はビビっと来ていない人がどうプログラミングと向き合うか，どうすればそんな状態でもしっくり理解してもらえるかです。極論，プログラミングを学んだ結果作れるものに対して価値を見出せていなければ学習意欲は上がらないなんですが，そんなこと言いだすと身もふたもないので，何とかしたいと思う所存。結果この文章が生まれました。

# プログラミング言語は「言葉」か
私がプログラミングが好きな理由は，書いたらコンピュータが動かしてくれることと，言葉として統一感があることです。自然言語は多彩な様々な表現が可能です。言葉の順番，言葉の出だしや終わり，話すときの情感など，本当に無数の表現方法があるからこそ，その組み合わせを試行錯誤することが好きです。でも，プログラミング言語は表現のバリエーションは自然言語より劣るとしても，自然言語にはない統一感があります（書き方に大いに左右されますが）。
だから，記述の意味を知るというよりも，今まで使ってきた言葉に置き換える，あるいはマッピングすることができれば，文系人間にはマッチするのかなと思います。そして今まで出会った中でも，言語能力が高い（と思われる）人はプログラミングの学習のスタートもスムーズな印象です。
プログラミング言語は人間が使うために人間が作り出した言葉です。ただ人間が普段使っている自然言語とはずいぶん違うものとも思います。使い方が違う。表現できるものが違う。でも，言葉ではある。この認識からスタートしたいと思います。

# 改めて「Hello World」：専門用語の壁
学習の最初なので，それぞれのパーツはよくわかりません。けれど「()」の中に入った文章が画面に表示されれることは，コードが動けば確認できます。たとえそれが，「どうやらそうらしい」という推測だったとしても。そして，その文章を書き換えると表示される文章も同様に変わります。問題は，この異質な文章を「納得できる形に自分の中に落とし込めるかどうか」です。

```java:HelloWorldを日本語でざっくり書くとこんな感じ.java
誰でも使える, HelloWorldというプログラム {
	誰でも使える, 固定のmainという名の処理, (文字列データの塊をargsという名前で取り混んで)動く {
		Javaの標準出力で吐き出す, ("Hello World"という文章)を;
	}
}
```

日本語で無理やり書いてみるとこんな感じでしょうか。残念ながら日本人の母国語，日本語と呼ばれるものは言語形態として主要プログラミング言語とはすっきりとマッチしません。脳内補完が大切になります。ややAppleのキャッチフレーズっぽい倒置法などを駆使して理解していくことになります。
どうしても専門用語的なキーワードから逃れられないので計算機システムを理解しようと試みることは避けられないのですが，人間も人間の社会システムを把握していないと言語化できないことは多いので，郷に入っては郷に従えという言葉に習っていきましょう。

# コピペで動くのは問題か
極論は「動けばいい」のです。ただし，なんかよくわからんけど動くっていう状態は非常に危ういと思います。日本人にとって日本語ができない人とジェスチャーのみで意思疎通ができることもありますが，相手の文化圏のよって間違って伝わる可能性があったり，実は伝わってなかったりっていうことが起きるのと同じです。意思疎通のツールとして言語が成り立つのは共通認識（「こういうものだ」という決まり事）あってこそです。その共通認識をすっ飛ばしたプログラミングは，1対1対応の硬直したプログラムになりがちに思います。
1対1対応を日本語で再現すると，「鶴と亀が滑った」という言葉と「犬と猫が滑った」という言葉の共通するルールがわからず，まったく別の関係のない表現として記憶（記憶）しているという状態のように思います。
実際に日本語を学んだときは周りの人間の真似をして言葉を覚えてきたはずです。印刷物を読み，新しい単語と文章に触れ，表現方法を学んできたはずです。本質的に学習はコピーを理解することです。
ただし，気を付けなければいけないと思うのは，間違った表現や言葉（「おいしい」をうまく言えず「おしい」と言ってしまったり）を常に周りと比較し修正しているという状態が表面に「目立って」出ているということでしょうか。人間の内部的には，したいこと（伝えたいこと）により最適な（周りと比べて正しいと思われる言葉遣い）に記憶を修正するという作業のように思います。それは純粋な1対1対応の記憶ではないでしょう。「やりたいことの言語化」のために，パターンの把握と，最適な単語の記憶にとどまるのではないでしょうか。前提として，「やりたいことが」決まっているという能動的な状態であることが重要です。
しかし，プログラミングはコピペで動いてしまいます。「能動的に何がしたいのか」を厳密に規定できていなくても，検索をかけてコピペしたら，「ぼんやりとやりたいと思っていること」が動いてしまったりします。
幼児が何でも「わんわん！！」と表現するのは単語が一致しないものの表現したいものは定まっています。「わんわん」と「指示したい対象」が一致すれば問題ないのですが，一致しなければ周りが想像して合わせるしかありません。そして多くの人は優しいの　で，「ワンワンじゃないよ，にゃーにゃーだよ」などと優しく伝えるのです。コンピュータはそんな人間臭くは動けません。
最初の言語の学習はこのまっさらであるが故のおびただしい量の反復とカテゴライズ・パターン分けなどを経て習得します。ただし，2個目以降の言語は下手に1つの言語を不自由なく操作できてしまう（と思ってしまっている）がゆえに，不自由さを感じ，なんだこのよくわからないルールと単語はという考えに容易に陥ります。周りが常時使っているわけでもないのでインプット量も極端に少なく，結果，「難解である」と切ない気持ちになってしまうのではないでしょうか。そもそも言葉は難解です。周りの人間の理解に助けられて私たちの言葉によるコミュニケーションは成り立ちます。でも自分が日本語をうまく使えていないと思うことはそう多くないのではないでしょうか。それは周りが自分の言葉を理解しようと善処してくれているからですが，なかなかそのことを自省する機会は少なかったりします。大体は理解してくれないという切ない思いでいっぱいになり終わってしまうのです。
プログラミングでは文法上の間違いは指摘してくれても，伝えたいことに対する相手のフォローはありません。そのため，私たちのプログラムは往々にしてコンパイラに伝わらず，あるいは間違って伝わってしまうのです。だから，コピペはではなく，そのコピペ元の言わんとしていることを理解し，伝えたい状態，伝えたい相手に応じて，適宜文章を書き換えるスキル（プログラミング能力）が必要なのだと考えます。

# 自然言語とは覚え方が違う
なんだか前項でだらだらと書いてしまいましたが，そもそも学習スタイルが異なるということにします。自然言語は多くの方が単語から学んだのではないでしょうか。「犬！」とか「猫！」とか繰り返して，感情を表現する方法を知り，単語の接続の「表現方法」を学びなどと進んでいくと思いますが，プログラミング言語は自然言語を知ったうえで身に着けるものです。シンプルな単語の反復による記憶はたぶんそれほど効果が高くないです。自然言語での名詞などは変数としてそもそもプログラムを記述する側が定義することですし，メソッドは同士や形容詞の意味を理解するということに近いからです。
でも，一度単語先行の身に着け方で身についてしまった以上，この感覚からうまく脱却できないことが障害となるのではないかと。学び始めに「.」で区切られていたりで「単語だ！」と認識し，全部名詞として学ぼうとしてしまう人がいるようです。だから「意味を理解して使いまわす」ではなく，名詞と同じ1対1対応で学習してしまい，結果，「どこに何を書けばいいかわかりません」という質問が飛び出します。大切なのは文章としてプログラムを書くという認識ではないかと予想しています。

# プログラミング言語は「依頼」をすることだけを考えた言葉と考える
自分の手足のようにプログラミング言語とキーボードを扱える領域の人には「？」が出るかもしれませんが，学習の一段階としてこういう状態があってもいいのではないかと思います。
* お願いするには，「誰に」「何を」お願いするかが重要です。それを明確にしましょう。
* お願いするには，詳しく説明する必要もあります。「どの動作をどういう順番で行うか」も明確にしましょう。
基礎の基礎は，この二つをどれだけ詳細に思い描けるかとにかかっていると思います。「味噌汁を作ってください」っていう一言じゃ足りないわけです。鍋に火をつけだしを取り，味噌を入れて味を調節しつつなんていうことを事細かに表現できることがまず必要です。
それができれば，あとは明確にした日本語での依頼文をプログラミング言語のお作法や文法に当てはめていくだけなので。「だけ」と言いましたが，その当てはめていく作業自体も最初の最初は難しいかもしれません。そもそも知識も経験もありませんから。でもここは恥を忍んでチャレンジしてはエラーを出し，その都度なんで動かないかを考えて修正する地道な作業しかないと思います。「わんわん！」と言っていたあの頃を思い出しつつ，その先の未来にできることに思いを馳せつつ，動かないことも楽しんでもらえればと思います。

# 結論
* 人間の思考のベースは自然言語
* 自然言語で考えたコンピュータに対して「やってほしいことを明確な手順でお願いする」のがプログラミング
* 相手に配慮して不足なく思いを伝えることができれば，プログラムは動きます

# 心に誓ったこと
* よりコンピュータを知ればお願いできることは増えるので，コンピュータがどういう存在なのかより勉強しようと思った
* 使うプログラミング言語の表現方法を知ればよりスムーズにお願いできるので，文法（表現方法）を学ぶことを忘れない
* 日本語や英語ももっと学ばなきゃいけない