すぐに試せる砂場をつくる

こちらは「Perl入学式 Advent Calendar 2015」の9日目の記事です。
qiita.com

昨日はいつもお世話になっています @tsucchi さんの「File::Basename の話。あるいはそこからの教訓的な何か」でした。
File::Basename の話。あるいはそこからの教訓的な何か - tsucchi の日記 2nd season

ここで言われていることは今まさに自分が直面している事でもあって、大変参考になりました。僕自身はこういった「より洗練された書き方への修正」というのは、ある程度基礎を習得して、全体が見えるようになってから(余裕ができてから)でもいいかなと思っていますが、仕事でプログラミングをしているとまた違うかもしれませんね。

さて掲題の件、じつは以前にも同じようなことを書いたのですが、
note103.hateblo.jp
今見たらもう1年以上前の記事なので、セルフ・リミックス的に現時点の目からあらためて書いてみたいと思います。

誰しも初心者の時には、基礎的な構文がまだ身に付いていなくて、かつ僕のように本職がプログラミングと関係なかったりすると、他のこと(というか仕事)をやっているうちに、せっかく覚えたこともどんどん頭から抜けていってしまいます。

そのようなおぼろげな状態で、配列やハッシュ、あるいは繰り返し文やリファレンスなどを組み合わせて使っていると、コードはなかなか思った通りに動かず、どこが間違っているのかを突き止めるのもひと苦労です。

「ハッシュの理解も怪しいけどリファレンスはもっと怪しい。while文もさっき何度目かの無限ループにハマったがなぜそうなったのかわからない……」というような。

そのような状況に陥ったとき、僕は次のような対処をします。

  1. 怪しいと思える要素、理解できていないと自分で思う箇所をそれぞれ最小単位(=最も単純な構造)に切り分ける。
  2. その一つを別の検証用ファイルに移して実行してみる。(必要に応じて変数名や値も単純なものに書き換える)
  3. もしそれがちゃんと動かなかったら動くまで修正し、動いたら元の箇所にその理解を反映し、動かしてみる。
  4. 元のコードがまだ動かなかったら、2に戻る。

これを根気よく繰り返していれば、コードは必ず動くようになります。

しかしながら、実際にそれをやるのは(とくに1や2を行動に移すのは)、そう簡単なことではありません。

というのも、プロのプログラマーであれば、そのようなトライ&エラーは日常茶飯事だと思われますが、初心者や非エンジニアのように、普段あまりコードを書く機会がない人は(少なくともそのような習慣がまだない人は)、そうした検証をすること自体がひと仕事で、それゆえなかなか原因を突き止めることができず、そのうちにコードを見ること自体が苦痛になっていく、という悪循環を辿りがちであるように思います。

そのような問題を解消するために僕がやっているのは、サンドバッグ的な、練習場のようなファイルを一つ作っておいて、わからなくなったら常にその同じ場所で、極端に単純な(簡単な)コードを試す、ということです。

具体的には、僕の場合は「perl.pl」というPerlスクリプトを作っておいて、動作を検証したいコードがあればそこで試し、検証が終わってもそこで書いたコードはそのまま。わざわざ消したり、どこかに移動したりはせず、もし次にまた別の検証したいコードが出てきたら、同じファイルを開いて「__END__」を記入し、以前のコードはコメントアウトした上で、新たな検証用コードを試します。

この「__END__」というのは、なぜかPerl入学式の講義資料はもとより『初めてのPerl』をはじめとする良質な入門書でもほとんど言及されていないようなのですが、perldoc.jpでは以下のように説明されています。

__END__ と __DATA__ は、 実際のファイルの終端より前にある論理的なスクリプトの終端を示すために 使うことができます。 これらの後にあるテキストは無視されます。
perldata - Perl のデータ型 - perldoc.jp

つまり、「__END__」を置くと、それより下にある部分はすべてコードの実行時には無視され、その上だけが実行対象となるわけです。

たとえば、以下のようなコードがあった場合、

#!/usr/bin/env perl
use strict;
use warnings;

print "Hello, ";
print "world!\n";

実行すると、

Hello, world!

と出てきますが、「__END__」を挟んだ以下のコードの場合、

#!/usr/bin/env perl
use strict;
use warnings;

print "Hello, ";
__END__
print "world!\n";

実行すると

Hello,

しか出てきません。
これを利用して、不要な過去のコードはすべて同一ファイル内の「__END__」以下へ押し流してしまい、それによって新たなファイルを検証のたびに作ったり保存したりするコストを削減するわけです。

ちなみに僕自身は、上の過去記事にも記したとおり、Vimquickrun.vimというプラグインを使うことにより、書いたコードをVim上で(別途ターミナルへ移動することなく)確認していて、またそのファイルもターミナル上で「px」と打つだけですぐ開くことができるため、通常は「試したいな」と思ってから実際にそのコードを書き始めるまで、5秒もあれば十分です。

と書きながら、本当に5秒で出来るのか……?と思ったので、やってみましょう。

f:id:note103:20151211012206g:plain

はい。厳密に何秒かはわかりませんが、少なくとも書き始めるまでは結構速いですよね。

ついでに言うと、その動画にもあるとおり、「__END__」を出すときには、「e」と打ってから「<C-j>」すれば出るようにsnippetに仕込んであります。
snippetについては以下に書きました。
note103.hateblo.jp

また、quickrun.vimについては以下あたりで紹介しましたが、
note103.hateblo.jp
note103.hateblo.jp

他にもところどころで書いているので、もし興味を持たれたらブログ内検索をしてみてください。(サイドバーに窓があります)

砂場の風景

もしも何かに熟達したいと思ったら、そのために必要なことは、センスよりも運よりも、ただひたすらの「繰り返し」だと僕は思います。これが仕事であれば、半ば強制的に(時には意志に反してでも)そうなるかもしれませんが、初心者や非エンジニアであれば意識的に行う必要があるでしょうし、「簡単に試せる練習場(砂場)」はその大きな助けになるはずです。

画家はいつでもすぐに仕事に取りかかれるよう、汚れてもいい服や、汚してもいいアトリエや、試し書きのできるドローイング帳を準備しているでしょうし、音楽家はすぐ手の届くところに楽器やレコーダー、メモ帳などを用意して、不意に降りてきたイメージを留められるようにしているでしょう。

そのような場所や道具を、どんな簡易的なものであってもいいので作っておきましょう、というのがこの記事の主旨です。

最後に、上のDEMOにも出てきました僕の練習場(perl.pl)をざざっと公開してみます。けっこう恥ずかしいですが、なかなか懐かしい感じもありました。

f:id:note103:20151211003226p:plain
まず今使っているファイルの一番下、つまり一番古い練習は1566行目でした。曜日を出すための何かをしてるんでしょうか。

f:id:note103:20151211003247p:plain
100行ぐらい上がるとAcme::Ikamusumeが出てきました。これは『CPANモジュールガイド』を見ながらやったのだと思います。

f:id:note103:20151211003253p:plain
さらに100行のぼりましたが、まだやってますねイカ娘。ポケモンの方も試しているようです。(同書より)

f:id:note103:20151211003308p:plain
これはデバックの練習でしょうか。木本祐紀さんの『業務に役立つPerl』を見ながら試していると思います。

f:id:note103:20151211003348p:plain
'Jotaro'と出てくるので、これは『雅なPerl入門』のサンプルコードですね。どうも本のサンプルを手元で動かしてみる、という使い方が多いようです。

f:id:note103:20151211003400p:plain
これは正規表現の練習。サンプルのボキャブラリー的に『初めてのPerl』あたりでしょうか。(後から気付きましたが、これでした)

f:id:note103:20151211003409p:plain
これは正規表現の行頭・行末アンカーの検証ですね。以下の記事につながっていると思います。
Perlの正規表現の修行の経過 - the code to rock

f:id:note103:20151211003536p:plain
えーと、200行以上のぼったんですが、まだ同じことをやっています。なかなか腑に落ちなかった様子。

f:id:note103:20151211003544p:plain
おそらく同じ時期、正規表現のワード境界アンカーの勉強。「YAPC::Asia 2015」で見たリカルドさんの発表の影響です。

f:id:note103:20151211003553p:plain
これはもう結構最近で、文字エンコーディングの勉強。utf8フラグを一所懸命確認しています。

f:id:note103:20151211003602p:plain
これはクロージャーの練習。夜中にふと気になって、西尾泰和さんの『コーディングを支える技術』を見ながら書いてみました。でもまだ余りわかっていない……。

ということで、このような一つ一つの検証、練習、勉強を、毎回いつも同じファイルで、パッと試してみています。
考えてみると、本当の勉強というか、自分の頭で考えるのは、最初に手元で実行した「後」にようやく始まるので(思ったのと違う……じゃあココを変えたらどうなるだろう?とか)、その「前」にかかる時間や労力は可能な限り少なくしたいですよね。
今回はそのための自分なりの取り組みを紹介しました。

本日の記事は以上です。明日の「Perl入学式 Advent Calendar 2015」は、僕と同じく生徒からサポーターに成られた @htk291 さんの「自分なりの役割について」です!
htk291.github.io

って、実際にはこれを書いてるのはもう12/11なので、そちらの記事もすでに読み終わっていますが、自分と同じところ、違うところがいろいろ実感的に読めて面白かったです。

Perl入学式の Advent Calendar はまだまだ続きますので、ぜひお楽しみください。
また、まだ空いている日にちが数日分ありますので、Perl入学式の受講生さんや関係各位、ぜひこの機会に参加してみてください!
qiita.com