読者です 読者をやめる 読者になる 読者になる

蛍光ペンの交差点[別館]

"どの点に関心をもつべきか ―をわれわれが学びとるのは,もっぱら仮説からだけである"

ズレに対する2種の賢さ

知性と呼ばれるものがある。賢さ、地頭、センスなどとも呼ばれる。

試験で測られる賢さは、最低点を超えていれば賢い。あるいは順位が高いほど賢い。

他人が判断する類の賢さは、期待を超えていれば賢い。知らなければ大抵賢いとなる。

ダメージに気づかないことも、時によっては賢さかもしれない。

 

それらとは異質ながら、生存に不可欠な賢さがある。
それはトラブル対応の秀逸さである。

 

たとえば妻の叔父(昨年以来会っていない)の名前を間違えて呼んでしまったとする。どのような応対が賢いのだろうか。気になっている相手を食事に連れていこうとして、15分歩いたあげく違う店の住所に向かっていたことに気づいた。どう対応するとこの関係は次に繋がるだろう。アルゴリズムの問題で定式化の種類が合っておらず解けない。気付くとしたら何をしたからだろう。

 

上司と約束した時間に現地に行っても上司が時間を間違えて来なかった。あるいはその逆。組んだ実験系の結果が想定と異なった。手順のミスか、前提のミスか、機械の故障か(『闘うプログラマ』には機械の故障が原因だと気づかず2週間プログラムを直し続けたプログラマの実話が出てくる)。

 

スーパーに車で行ったら駐車スペースがなかった。大事なプレゼンの前日に高熱が出た。納期に間に合わないと相手から告げられた。どうしても問題が解けない。誰に相談するのが得策だろう。

 

第一志望の大学や会社に落とされた。想定していたものとは異なる同僚、設備、業務のなかで、何を考えるのが秀逸な対応だろうか。大切な存在と死別した。天災に遭遇した。齢50にして生き別れの息子がいると告げられた。3億の借金を負った。

 

もちろんいくつかの問題は、そもそも問題になる前に予防すべきだという意見もあるだろう。ではそのようにして予防できるものをすべて除いたとする。そのあとにまだしつこく残る、起こりうるトラブルに対する対応力だけでいい。これは他のことを考えるための文章ではない。

 

これらのトラブルに対する対応の「秀逸さ」をどう言葉で表現するのか、それが実は難しい。僕が思うに、秀逸な対応をする人は必ずしも自信満々ではない。自分の行なった対応が見事であることを認識すらしていない。むしろビクビクと怯えていたり、はためにはみすぼらしく見えたり泥臭く見えたりする。高熱なんか出たときは意識すら朦朧としている。だから「秀逸さ」はいつも事後にそう評価される。

 

他に強調すべきこととして、対応結果が芳しくなくても構わない。優れたプレゼンは必ずしも一位にならない。あるいは結果が好ましくてもたまたまであれば必ずしも秀逸な判断だとは言えないだろう。だから秀逸さはリターンそのものでは定義できず、リターンの期待値でしか定義できない。

 

つまり秀逸なトラブル対応力と表現できるその賢さは、トラブルに際して高い期待値を持った行動をすぐさま取れるか、ということになる。これは、思うに性格とスキルである。

 

以上が1種目の賢さである。そしてもう1つある。
トラブルに対する解釈転換の秀逸さである。

 

自転車で行こうとして雨が降ったとき「たまにはバスもいいか」と考える。部門が撤退して解雇になったときこれもまた人生の不条理と割り切る。電車で変人(a fruitcake)に出くわしたとき、愚痴るのではなく何両目に乗ると最も確率が低くなるか考えてみる。最近習った多腕バンディット問題の枠組みが適用できないかダメ元で検討してみる。

 

好きなことを仕事にしてみて理想と現実が違ったとき「なるほど、これとこれを解決すれば理想の職場になるのね」と問題解決の枠組みを追加する。転職先の要件を満たしていない時にスキル習得過程を具体的に考えてみる。ぶどうを酸っぱくする以外にも、思考はいろんな道を僕たちに提供してくれる。

 

思考の賢さは、外からは見えにくい。作業をしている本人だけの問題である。しかし、1つ目の賢さを含意する行動の実施には、このようなある種のポジティブ思考が重要、いや実は不可欠であると思う。そしてそのポジティブ思考は同じ局面でも複数存在する。シェリル・サンドバーグは、高い学業成績を「お母さんが助けてくれたから」以外に「What a damn question ... I'm awesome!」と答える学生も居る、と述べている。

 

 

歩き出す前に見えた地平線がおぼろげな様を、どうかずっと覚えておこう

明後日から違う街に住む。

 

生きていることの楽しさは、まったく新しい世界に飛び込んで、望んでいたものを狙い通りに得ることや、あるいは関わりたくなかった面倒事に巻き込まれることや、予想外の喜びに遭遇して立ち尽くすなかにあると思う。上京したときや、初めてLinuxに触れた時や、初めて投資の考え方に出会ったときはどれもそうだった。

 

僕が学部の4年間でもっとも感動した授業は、高校のときに抱いていた興味とはかすりもしない分野だったし、投資の世界でROIやシャープレシオといった考え方に出会ったのは、ある意味では予想外の僥倖だった。初めてのLinuxのデュアルインストールで13時間も無駄にすることになるとは思っていなかったし、100時間ぐらいかけた調査資料をゴミのように扱われる(そしてその主張を自分が心底から納得する)機会が来るとは思っていなかった。予想はタイにもなるが、マイナスにもプラスにもズレて、総じて僕の場合、事前の予想よりも豊かになる。今回はどうだろうか。

 

予期していることはいくつかある。狙っていることも、あわよくば掴もうと思っている機会も存在する。でも実際には、思いもよらなかったようなトラブルで泣きたくなるような日々を過ごしたり、20数年生きてきてさんざ広げてきたはずの思考空間のどこにもない文化や価値観に新大陸発見されることもあるだろう。不確実性を乗りこなすなどとはとても言えない。僕の性格では不格好に踊らされるが関の山だろう。それで構わない。したり顔の満足気で居たいのなら、そのまま同じ街で先輩風を吹かせていればよかった。

 

いま自分が精一杯に目を凝らして見える、それでもおぼろげな地平線のことを、よく覚えておこうと思う。きっと来年再来年には、くっきりはっきり悲喜こもごもな世界になっているだろう。おぼろげな足場でも向かうと決めたときのことを覚えておこう。環境が敵意をなくすまで、そしてその後も。勇気の話である。

 

思考の歯磨き

内田樹は批判されることも多いが、彼の『日本辺境論』を読んだ時にとても腑に落ちて、そのまま今でも覚えている一つの主張がある。それは、本書の主張はこれまで別のところでも散々言われてきたことで何の目新しさもないが、歯磨きのように定期的に見直すことで価値が高まるものであるだろう、というものだ。

 

なるほど、確かに思想はただ一回の目新しさ以外にも評価軸がある。むしろ微視的には、内容ですらなく頻度が最重要だとすら受け止められる。思考について研究開発をする人たちは、よし俺は私は先行研究を踏まえて新規性と有効性を出しきったゾと満を持して次回作に移っていいのかもしれないが、読者は違う。私たちは本当に大切なことでも忘れてしまう。頻度の多い思考にダメなものが混ざっていると、その波に押し流されてしまう。歯磨きを、しなくなってしまう。

 

脳内思考は、書き手と読み手が全く同一という点で、極めて特徴的な情報である。日記も同様ではあるが、1日や1時間といったように規模が荒い。ミニ日記ことツイッターの玄人は5分単位で感情を記録するのかもしれないが広範囲に見られる現象ではない。よって、私には、脳内思考をメンテナンスすることはとても重要なことであるように思える。いわば思考の歯磨きである。

 

単語が集まって文を作り、文が集まって文章を作るように、とまでは行かないが、一日を終えた感想は(その日に)書き込んだ(「磨いた」)脳内思考(の列)に大きく左右される(ような印象を受ける)。たとえ同じできごとがあった日であってもだ。私たちは書き手として大きな責任を、また読み手として大きな影響を受けている。歯磨きについては標準化された歯科衛生士の指導を受けるのに、思考習慣については指導を受けないでよいのはなぜだろう?

 

いや、実際には教育(家庭も含むだろう)の中で指導を嫌というほど受けている。ものを見たときに、まずは覚えろと言われて育つ。常用漢字も九九も覚えていない段階では当たり前だ。だから私たちはいくつかの思考習慣を自動化させている。その次に理解しろと言われる。更には批判しろ、改善しろと言われる。社会に出ると、定期的な思考習慣のどれかが腐っていて、それを個別に治療されることもある。

 

歴史は、歯磨きのようには語られない。
ただ重要な事実が初出時を優先して要約されるのみである。
しかし生活は要約ではない。

 

歴史からは学べないここの空白で、ひとりひとりはどんな歯磨きをしているのだろうか。

命令で済むということ

仕事の遂行が命令で済むというのは面白い。プログラミングの話である。プログラムは事細かに指定された命令の並びであり、予期通りの結果を一度正しく生じさせたプログラムは疲れ知らずの有能な働き手となる。

同じ結果を再現といえど無論、実際は占有やら老朽化やらで、再現性あるはずの操作が前回と異なる結果をはじき出したりと、そこまであっさりと話は片付かないのだが、学び始めだとそう思い込んでしまいそうなぐらいにこの道具は強力で、使い手はややもすると夢を抱いてしまう。

過去の活用という文脈で考えてみると、例えば勉強をしていてノートをとるときに、たまに紙面構成をじっくり考えてみたくなることがある。覚えやすい記憶のかたちを選んでいるとも言えるし、未来の自分が特定の順に目を通すように「仕向け」ていると言えるかもしれない。その点でプログラミングは筆写や清書と共通の側面を持つと思う。一方で冒頭に述べた「勤勉な無給労働者を生み出す」ことはプログラミングの特殊な側面である。自分より優秀で勤勉な働き手に、自分がやりたいことを無償で委託できる。こう書くと、近代はとてつもないものを生み出したのだなとふとしみじみする。

やりたいことはありますか

人生でやりたいことが明確に決まっている、というと大なり小なり驚かれることが多い。僕の世代の人々は学生であれ社会人であれ自分のやりたいことを持っていない人が多いからだろう。

 

ただ残念ながら僕は子どものときから一つの夢を追いかけているようなビリーバーではないし、今やりたいことだって今後も変わらないとは限らない。僕のやりたいことが決まっている理由はどちらかというと今後の決断に安定感を持たせる意味合いが強く、その意味でとても冷めている。情熱のなかで夢中になれる人はそれはそれで羨ましいと思う。ただし、全く熱意がないかと言うと、そうでもない。

 

僕にとって「やりたいこと」とは集合名詞であり、構造としては優先度付きキューにとても近い。

 

もうすこし具体的にたとえて言えば、「やりたいこと」という言葉を聞いたとき、病院の待合室のような風景が思い浮かぶ。その待合室にはいくつかの「目的さん」たちが座っていて、彼らにはそれぞれ背番号のような数字が割り振られている。待合室の管理者は、もっとも数字が高いものを最優先して診察室に向かわせる。呼びだされた「目的さん」は向かった診察室で、はたして実現可能なのか、何年ぐらいかかりそうなのか、初手として何をすべきかをいろいろと調べられる。

 

優先度付きキューなので、最後に待合室に入ってきた「目的さん」であっても、その数字が高ければ最優先で診察室に向かう。

 

僕にとって今の夢は、その数字がいま自分の中で最も高いものにすぎない。

 

数えたことは無いが、おそらく待合室には20から30程度の患者が座っている。僕は怠惰なのでほんとのことを言うとずっと部屋で寝ていたいのだが、そいつを診察室に入れると一生何もしないままなので8時間以外は静かにしている。

 

この待合室は僕が息を引き取るまで空になることはないだろうし、その意味でやりたいことは生涯なくならないだろうと思っている。数カ月後からはまた生活環境が変わる。診察が必要な数はまた増えるだろう。

書くということ

僕にとって文章を書くことは、僕のなかでの重要な意味を持っている。高校のときからブログへの投稿数で数えれば1000以上の文章を書いてきた。

 

アウトプット(生成物)であることは間違いない。外に対して自分が感じた何かを表現したり、あるいは「こいつは貴重だ」と感じた文言や主張を反芻したりするために使ってきた(ような気がする)。数十時間かけて何度も推敲して書いた文章のことは何年経っても結構覚えているし、一度文章にすると人と話していてその話題になったときに結晶を差し出すように安心して話せる。自分の出せるなかでは最上のものなのだ、と自分で納得できている。話していて、自分のことばが辿り着く先がクリアに予測できて、きちんと狙い通りにそこに落とせる。人と話していると考えがまとまる、という経験があるが、それに加えて僕は書いていると考えがまとまる、ということを自然と経験して育ってきた。

 

僕にとって文章は売るものではない。あくまで自分の活動の中間生産物であって、上記のように普段の活動を明確化したり、重要なことを再確認したりするための手段に過ぎない。生計を立てる手段として考えたことは一度もないし、たまに友人から褒められて嬉しくなる、その程度の素人の手遊びにすぎない。

 

高校1年生のときから比べると、書く頻度は驚くほど減った。数十分の1程度になった。無駄な情報を書くことは嫌いだし、こういう文章を書いていてもあれこれ表現を消したくなる衝動に駆られる。筆が走るのに任せて書く、という友人の指針には一理あると思う一方で、一方で骨以外何も残さないぐらい質朴な文章にしたい嗜好もある。どちらが良いのかは今でもあまりよく分からない。こういう自分語りを読むのが好きな人は暇な人が多いから、少しぐらい助動詞が余分でも気にしないのかな、と最近は思ったりする。

 

誰に対して書いているのか、というのも実際あいまいなままである。高校時代は、僕を知らない人たちが読んでくれると一番正のフィードバックが生じていた。いまはネットが大衆化したせいもあって、半数ぐらいは知人だ。それが嫌だというわけではなく、高校生の僕はその開放性にどこか期待していたということなのだ。少なくとも僕にとってはそういうものだった。

 

英語で書けたら世界はどう映るだろう、と思うこともある。それにあと何年かかるだろうか。英語は現在は文法ミスで躓くレベルで、とてもじゃないが気持よく書けるレベルに達していない。人工知能機械翻訳で人間の翻訳作業は不要になって、はいはいそういう話はどうでも良くて、僕が単にそうしたいのだ。僕の個人的な感情や、感想や、記憶を、タイプという行為を通してタテモノみたいに構築し、できあがりの悪い作品のことは都合よく忘れて、そこそこよく書けた作品についてはどーよこれと鼻高々で得意気になる、そういうことをしたいのだ。

 

ここまで書いていて、ああそうか、文章を書くことは、

僕にとって趣味だったのだと初めて気がついた。

プログラミング学習の論点が変わるとき

昔はいろんな言語に手を出していた。C++から始まって、JavaRubyPython、C、HTML、CSSJavaScriptPHPなどのポピュラーなものから、LISPHaskellOCamlR言語などの比較的マイナーなものまで。

 

しかし最近はめっきりC++R言語以外は使わなくなった。研究とバイトで使うのがその2つしかない(上に他に道楽的に手を出す時間がない)ことも理由の一つだが、それ以上に自分のプログラミング学習における論点がシフトしたことが大きな要因だと思う。

 

プログラミングを始めた当初は、とにかくプログラミングの一ステートメントを書くこと自体が課題だった。やりたい作業を実行するためにはどの関数が必要なのか、なぜ予想したかたちでデータが返ってこないのか、この配列/リスト/データフレームというデータ構造はどう操作できるのか、それが「学習」の中心事項だった。だから、他の言語で似たような構造をたくさん見ることが、結果的に学習に貢献していた。X語を勉強したことがY語の勉強にもなっていた。

 

いまは、プログラミングの100ステートメントの配置について課題がある。何十通りも書き方がある中で、どれが最も効率的に(書くのにかかる時間や、特にその後のメンテナンスにかかる時間の面で)書けるのか、そこに関心がある。

たとえば次のような関心だ。

  • 研究用に使うスクリプトは、少しだけ処理を変更して(たとえば10行の処理で5行目だけAではなくBというデータに注目して)同じ処理をしたいことがある。これは関数として抽象化して、引数でAかBを与えるべきだろうか?

できるんだからすればいいじゃん、と昔の僕は思っていた。しかし事態はもう少しゆっくり考えてみる必要がある。

 

「最初は1つの処理で済むと思っていたものが、実はAかBかを可変にしたい」というニーズが生じたことで、

someProcedure()

someProcedure(selected="A")

someProcedure(selected="B")

と渡す、と作成すると実はあとあと大変なことになる。というのも、研究が進むと「じゃあ5行目だけじゃなくて7行目も変えたらいい結果が返ってくるんじゃないだろうか?」とか、「8行目はどうだろうか?」と無数に可変にしたくなってくる。結果として、

someProcedure(selected="A")

someProcedure(selected="A", selected2="C")

someProcedure(selected="A", selected2="C", selected3="D")

someProcedure(selected="A", selected2="C", selected3="D", selected4="E")

someProcedure(selected="A", selected2="C", selected3="D", selected4="E", selected5="F", ... selectedN="XYZ")

と、際限が付かないくらいに長くなる。

これで、関数が

someProcedure

someProcedure2

someProcedure3

...

someProcedureN

 

と無数にあった場合はもっと最悪なことになる。コピペ・コンテストだ。

 

そうなると、次はデフォルト引数(selected2を与えなかった場合に、既定として使われるselected2の値)が問題になるし、一度書いた関数の呼び出しが。

someProcedure(selected="A", selected2="C")

 

だった場合、

someProcedure(selected="A", selected2="C", selected3="D", selected4="E")

 

にしたあとでも同じ動作をするように保証するべきか、という話も生じてくる。つまり、保存しなければいけない状態はどれか?という複雑性が生じてくる。

 

これに対して、現状僕がR言語で(現在はR言語スクリプトを書いている)取っているベストプラクティスは、処理の分岐に関わるフラグを集約した list型の変数 procedureOptionList を宣言することだ。こうすると、

 

getProcedureOptionList <- function( ){
list(a = '/Users/update/160421/result.html',
     b = c("a", "b")[1],
     c = c("c") )
}

procedureOptionList <- getProcedureOptionList()

someProcedure(procedureOptionList){       # 引数の数を書き換える必要がない

  procedureOptionList$a       # どの処理フラグについても自由にアクセスできる

  procedureOptionList$b

 

}

 

のように、処理フラグが追加されても、関数の引数は procedureOptionList の1つだけで一定なので、書き換えなければいけないデフォルト引数の箇所はおおよそゼロになる。この一工夫を導入してから、「あっ、さっき追加した変数、関数Aのデフォルト引数には設定したけれど、関数Bには設定していなかった」と言ったような、ケアレスミスによるエラー遭遇率が格段に減った。新しい処理フラグを追加するときも、「getProcedureOptionList関数のなかに追加すればいいんだ」と意思決定と行動もグンと早くなり、認知負担は激減した。深夜2時に寝ぼけて書いていてもミスる可能性が減っただろう。プログラミングで「メンテナンスを容易にする」というと、それは「理由の分からないバグが出ていて何時間で直せそうかわからなくて怖いのに、締切は5時間後に迫っていて、しかも2日寝てなくて頭は朦朧としてる」みたいな最悪の状態でもギリギリ間違えないくらいの簡単なタスクにできる工夫を事前に随所に散りばめてある、という意味合いのことである。

 

 

このような話題は、入門書では扱われない。list 型の変数は、たんに「可変長の要素を持てる」や「 vector 型と異なり、要素それぞれの変数の型は同一でなくてもよい」などと文法的な説明がなされるだけだ。実際にどこで使うと破壊的にミスが減るのか、未来のバッドコンディションなあなたを助けてくれるのか、というのは範疇外である。

 

そしてこのような一工夫は、どちらかというと言語依存だ。もちろんRの list でできることを 別言語のデータ構造で実現することは容易だろうが、依存とはそういう意味ではなくて、プログラムの書き手がその言語の文法を前提として考えるという意味だ。「listは可変長の要素を持てる。では引数に指定したら、引数がn個に増えたとしても一生書き換えなくて済むんじゃないか?」という判断を、言語非依存に「可変長の要素を持てるデータ構造を、引数として使うことで拡張性を維持したまま複雑性を減らす」と学べるとは信じがたい。そのような知見はむしろ、Rで一度そういうことを経験したから他の言語でもできないか、というときにそうやって抽象化されるものではないか。

 

 

 

だから、自分がよく使う言語の、よく使う文法の、まだ気づいていない活躍の場に対して論点が集中している。Pythonではどうだとか、OCamlだとこう書けるとか、そういう話はどうでもよくなった。そんなことの比較に認知資源を割けるほど、目の前のプログラムは浅くない。自分が入門書やネットの記事で見てきた、浅い検討しか成されていないプログラムで「学んでしまった」書き方を、批判的に見て別案(繰り返すが、別案は1つではなく、数十通り存在する)を出し、それが実際に動くか試すのは、それだけで作業時間が潰れる。しかしそうしないと、新しく追加した引数を100個の関数にコピペし続けて、一つでも抜かしたらエラー、みたいな知的でも何でもない、無駄に集中力だけ必要な作業になってしまう。(ちなみに、たまに「研究用に使うプログラムなんて大したことないから、別にすぐ書けるようになるよ」みたいなことを言う人がいるが、そういう人が書いたプログラムを見るとこのような検討がなされていないことが多い。きっとものすごい時間を投下して修正しているか、それともバグがあるまま研究して間違った結果を出力しているかのどちらかだと思う。こういう間違いは公開したらすぐに他人には気づかれるので、ソースコードを公開する文化が根付かない遠因の一つにもなっていると思う)

 

言ってみれば、自分が普段使う言語のよく使う関数や型をほぼ暗記したあとでも、いやむしろその後こそ、より一層プログラミングは学ぶことが増える。日本的な暗記学習の弊害なのかもしれない。ググらなくても思い出せることと、目の前の複雑性を軽減させるために適切な場所に使えることは、けっこう違う。