プログラムで問題を教えるということ
また日記の間があいてしまった。
このエントリーは、プログラミングを教えることについての話ではないことに注意。ある問題がある。この問題をどういう手続きを用いれば解くことができるか、という手続きを教えたいということ。それこそがプログラミングの本質という意見もあるかも知れない。しかし個人的にはそれは違うと考えているのでこのエントリーを書く。なお、以下の話はよく考えるとちょっと頭が悪い話になる。あと、使用されている言語は特に何も考えていない。ちょっとPascalとかを思わせる言語になっているような気もするが。
たとえば、だ。4つの変数a, b, c, dがあるとする。ある2引数関数fooを、これらの変数のうち相異なるものについてすべて作用させたい。ただし、foo(a, b)とfoo(b, a)は両方実行する必要がある。
つまり、
foo(a, b); foo(a, c); foo(a, d); foo(b, a); foo(b, c); foo(b, d); foo(c, a); foo(c, b); foo(c, d); foo(d, a); foo(d, b); foo(d, c);
と書きたい。全部で12行。ちょっとプログラムを知っている人であれば、言語にもよるが次のように書くだろう。
array = {a, b, c, d}; for i=1..4 for j = 1..4 if i != j foo(array[i], array[j]); end end end
もし仮に、a, b, c, dという4変数が10変数になったとしても、ちょっと書き換えればそのまま使うことができる。さらにiとjのループをsize(array)回にしておけば、配列を書き換えるだけでいい。保守性に優れたbetterなコードだ。保守するつもりなら。
ところが、教育で使うのであれば、保守性はあまり問われない。求められることは、「難読でないこと」と「バグがないこと」の二点だけだ。「バグがないこと」において、冗長なプログラムは悪くなりうるが、この例のように4変数くらいならバグが入る余地は極めて少ない。それどころか、たとえば、下の例のようにi != jというところがi=jとかになってしまったりするようなバグだってありうるのだから、一長一短だ。そもそも、動作確認するのは当たり前なので、そこで動いていればあまり問題はないだろう。
重要なのはむしろ、どちらの方が読みやすいのか、だ。どちらが読みやすく感じるだろうか。意味が伝わりやすいだろうか。後者のプログラム方が、伝わりやすいという人は、おそらく相当にプログラムを読みなれている人だと思う。ただそういう人は、無意識的に後者の例のforループを展開しているんだと思っている。
で、だ。何が言いたいかといえば、個人的に前者の例は悪くないのではないかと。一部の学生に、後ろ指を指されて笑われるというリスクさえ取れば、あとは問題にならないのではないだろうかと。で、そんな学生に笑われたところでどうかなるような、そんな神経の細い人は教えるのに向いてないと思われるので(暴論)、やっぱり前者でいいんじゃないのかな、と最近思った。