自分が普段やっている新しいプログラミング言語を効率よく覚える手順

# tl;dr
- ある程度プログラミング出来る人が、新たにプログラミング言語を覚えなきゃいけないときは以下の手順でやると効率が良い、と思って実践しているので紹介します

1. ゴール（やりたいこととか）を設定する
2. サンプルコードのコピペや書籍の写経などをしてやりたいことができるものを手元で動かせるようにする
3. そのコードを理解することをゴールとして、分からないところをピンポイントで勉強していく

# まえがき

## 想定する読者像
- なんらかのプログラミング言語をある程度知っていて、そのプログラミング言語のリファレンスを常に見なくても、普段の自分の用途においてなんとなくプログラミングができている

## このqiitaで書かないこと
- 全く経験がないプログラミング初心者がプログラミングできるようになる方法
- 全く経験がないプログラミング初心者が最初のプログラミング言語を勉強する効率の良い方法
- 効率の良いググり方
- 効率のよいリファンレスの読み方・探し方

# 新しいプログラミング言語を効率よく覚える手順

## 1. ゴールを設定する
手段はともかく、純粋にやりたいことをゴールとして設定してみる。

純粋に、目的もなくただプログラミング言語だけを勉強する人もいるかもしれないが、多くの場合、人は何かをするためにプログラミングを覚えると思う。（そうでない人がいたらごめんなさい :bow: )
だから新たにプログラミング言語を覚える場合にも、何らかの目的があった方いい。

初めからやりたいことがある人はそれでよいが、思いつかない場合であってもがんばって設定してみよう。
例えば、過去に自分が新しいプログラミング言語を学習した時のは以下のようなものだった。

- 掲示板っぽいウェブアプリケーションが作りたい
- iphone買ったしios app作りたい [^1]
- webサーバーをsocket関数使って書いてみたい

上記の例はふわっとしてるので、このQiitaはもう少し最近の、かつ具体的な例を使って説明してみる。

筆者はある日、pythonで[BigQuery](https://cloud.google.com/bigquery/)から取ってきたデータを集計したいと思った。
社内でデータ集計のタスクが発生したので、せっかくだからと[jupyter notebook](http://jupyter.org/)を使ってみたかったのである。[^2]
最終的にはpython上でデータを加工してCSVに出力したりグラフを画像として出力したい。これをゴールとする。

## 2. ググッて見つけたやり方をとりあえずやってみる
ググって見つけたブログ記事に書いてあるコードでも、公式リファレンスにあるサンプルでもなんでもいいので、それをコピペして動かすところから始める。そのコードが何をしているのか詳細に知らなくてもいい。まずは「やりたいことが大体できるコード」というコードを手元に用意して動かすところからスタートする。

今回は `pytyon bigquery 集計`みたいなキーワードでググった以下のコードを動かしてみることにする。なお、このときpythonは全く書いたことがない状態だった。

```python3
import pandas as pd
project_id = 'my_project_id'
query = 'SELECT * FROM tbl'
data_frame = pd.read_gbq(query, project_id)
```

この時点で筆者はpandasが何なのか良く知らないし（rebuild.fmで名前を聞いたことがあるぐらい）、`import pandas as pd`が何をやってるかも知らない。また、BigQueryに投げたQueryの結果が入ってそうな `data_frame` をどうやって操作するのかも知らない。

とりあえずjupyter notebookのセルにコピペして動かした所、それらしい結果が返ってきた。とりあえずは、これを理解したいとする。

コピペはいけないんじゃないの？とよく言われるし、実際productionで動くコードで何も考えずに適当にコピペしたコードを入れるのはよくないと筆者も思うが、プログラミング言語の学習において、コピペは効率の良い学習方法である。

プログラミング言語に関する本を頭から読むと、序盤にそのプログラミング言語のsyntaxや型やデータ構造についての説明、中盤に標準ライブラリの紹介、後半に実用例とか3rd partyライブラリの紹介とかそんな感じの構成になっていることが多い。そのためか、プログラミング言語を新しく勉強するときには、まずsyntaxを覚えて標準ライブラリの使い方を覚えて…という手順で順を追って勉強しがちだが、実際の用途においてそれらの知識が全て必要なケースは少ない。

プログラミング言語の機能としては備わっていても、実際のプログラミングでは使わない機能というのは結構ある。或いは、標準ライブラリがあっても、もっと使い勝手のいい3rd partyライブラリが存在していてそっちがデファクトスタンダードになっていることもよくある。
なので、いざ何か書こうとしたときに、時間をかけて勉強したことが実践ではあまり使われてらず、3rd partyのライブラリについて改めて調べ直す、ということが往々にして起こる。 [^3]

そのため、まず世の中一般で行われているアプローチをそのまま採用して、手元で動かすことからスタートし、詳細に知る必要がある部分だけをピンポイントで学習していけばいい、と筆者は考えている。

## 3. わからない所だけをピンポイントで調べる
手元には「なんかよくわかんないけど動いてる」コードがあるとする。次はこのコードを理解するフェーズである。

例えば先に提示したpythonのコードを理解したいとする。

まずこの１行。

```python3
import pandas as pd
```

`import`とあるからライブラリをloadして使えるようにしているんだろうなと当たりがつく。
なので、pythonのリファレンスのチュートリアルにある[6. モジュール (module)](https://docs.python.jp/3/tutorial/modules.html)辺りを読んでみるとよさそうだ、ということになるので読んでみると大体知りたいことが書いてある。
一方、 `as` というキーワードについての説明がpythonのリファレンスをいくら読んでも見つからなかったのだが（たぶん探し方が悪いだけなんだろうけど）、ググるといくつかのサイトで `importしたpackageに別名をつけて参照できるようにするための機能` ということで説明が見つかったので、とりあえずそう理解しておく。 

ローカル変数の定義はなんとなく見れば分かるので飛ばすとして、次はこれ

```python3
data_frame = pd.read_gbq(query, project_id)
```

ここでpandasのメソッドを呼んでいるので[pandasのリファレンスを読む](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_gbq.html)。冒頭に `Load data from Google BigQuery.` と概要が書いてあり、引数の説明と、返り値のクラスが `DataFrame` というクラスであるということが書いてある。

このメソッドには７個のoptionalな引数があることが分かる。
各引数の解説を読んでみると、最低限以下のことがわかれば実用上は問題なさそうだった。

- StandardSqlを使いたい時は `dialect='standard'` としなければならない[^4]
-  BigQueryにアクセスするためのCredentialはjsonファイルそのものかファイルパスを `private_key` という引数で指定すればよく、未指定の場合はDefault Credentialsが使われる

残りのoptionは多分めったに使わなさそうなのでスルー。

ところで、このメソッドの返り値のクラスは `DataFrame` と書いてあるが、このオブジェクトからどうやって値を取り出すのだろうか。pandaのりファレスを読むと[DataFrameのメソッドの解説](http://pandas.pydata.org/pandas-docs/stable/api.html#dataframe)はあるのだが、もう少しサクっと使い方を知りたい。もっと簡単な説明はないか、と探すと[10 Minutes to pandas](http://pandas.pydata.org/pandas-docs/stable/10min.html)というページがあった。このページにDataFrameや他にもpandasが提供するデータ構造を表すクラスの使い型がまとまっている。これを読めばDataFrameのオブジェクトとして格納されたBigQuqeryのレコードをごにょごにょする方法が分かりそうだ。

## 余談: より良い方法を探し過ぎない

さて、上記の手順を繰り返し、pandasを使ってデータの集計やグラフの出力ができたとしよう。そろそろpythonにもpandasにも慣れてきた頃だ。
しかしpandasで本当にいいんだろうか？もっといいライブラリがあるのではないだろうか？と探したくなる時がある。筆者は実際探した。

しかし、ここで新しい方法を探すのに時間をかけすぎるのはよくない。

今、自分のゴールのために問題をうまく解決できている方法があるなら、経験上その方法を深く掘っていった方が、単位時間で覚えられる機能やsyntaxの量は多くなる。新しいライブラリやツールはも初期の学習コストが高く、本質的でない部分（setupやドキュメントの読み方etc）の学習に時間がかかる。また、そのライブラリやツールが自分の目的に合っているかどうかわからなかった場合ちょっと損だ。 [^5] だから、ツールの検証がゴールならそれもよいが、プログラミング言語の学習が目的であれば、まずは１つの方法について深く知ることをおすすめしたい。

# まとめ

以上、筆者が普段新しいプログラミング言語を勉強するためにやっていることを言語化してみました。

筆者は今年pythonとdlangを新たに覚えましたが、pythonの場合は主にnumpyやpandasを使ったデータ集計や、digdagのworkflowで使うちょっとしたscriptを書くのがゴールでした。dlangについてはあまり目的がなく「ただ気になっていたので勉強したい」という感じでしたが、一応[今年のアドベントカレンダーのネタ](
https://qiita.com/seri_k/items/a757a87bf78edde00b80) にはできました。

来年も何かの用途で新しいプログラミング言語を最低１つは勉強したいですね。

[^1]: なお趣味で勉強してたら急遽仕事でiosアプリを納品することになって、慌てて調べまくって頑張って作った思い出がある
[^2]: data sourceがBigQueryなので[Cloud Datalab](https://cloud.google.com/datalab)を使っても良かったのだが当たり前だがGCEインスタンス分の料金は発生するので手元で動かしたかった
[^3]: もちろん、プログラミング言語の隅々まで勉強することは、そのプログラミング言語の思想を知ったり、ライブラリを作る時には役に立つであろう知識を得るという観点では役に立つので無駄という訳ではない。
[^4]: なお筆者は実際これに気づかずにStandardSQLで書いたSELECT文がsyntax errorになってハマった
[^5]: 全くの無駄ではないと思うが、プログラミング言語の学習と自分がやりたいことの実現という２つの目的からはやや非効率という意味で