中学校でラノベ持ち込み禁止になったお話

唐突に中学時代のことを思い出したので書く。2014年とかそこらのお話。どこの中学校でもあるのかは分からないが、私の中学校には朝読書の時間があった。朝の15分くらいを読書の時間とし、自分で持ち込んだ好きな本や、教室に置いてある学級文庫の本を読むことになっていた。読んで良い本に明確なルール等は引かれていなかったが、基本的に漫画とかでなければなんでも良かったように思う。一時期流行ったワンピースの考察本とか、あるいは厨二病らしく神話の本とか、各自が思い思いの本を読んでいた。そんな中で一番人気があったのはライトノベルだ。これは別にオタクグループに限った話ではない。当時はもはやオタクに偏見があった時代とは違い、いわゆるカースト上位の男子もアニメを見ている時代だった(少なくとも私の地域では)。文章が簡単で中学生の頭でも読みやすく、内容が刺激的なライトノベルカースト問わず広く愛されていた。正直エロい挿絵が入っているライトノベルも多く(というか中学生男子なのでそれが目当てではあるのだが)、教師としては喜ばしくなかったはずだが、変に規制を儲けるのもアレなので黙認していたんだろう。

また、本の貸し借りも頻繁に行われた。というか頻繁に行われすぎてもはや所有者が不明な本が流浪していた。記憶している限り、特に人気だった作品はバカとテストと召喚獣だった。そう、時代を考えると少し古い。バカテスのアニメの放映はとっくの前に終わっていたし、ラノベの刊行は続いていたとはいえ少し世代が違う。これはなぜかというと、地元に本屋がなかったからだ。こう書くとめちゃくちゃ田舎に思われるかもしれないが、少なくとも学校から最寄り駅の範囲でライトノベルを売ってるような本屋はなかった。代わりに駅前に小さい古書店があり、そこで買われた中古のライトノベルが学校で流通していたのだ。少し前に流行ったバカテスが人気なのはこういう事情による。他にはとある系も人気だったり、IS(インフィニットストラトス)は私が持ち込んで流行らせたりした。流行らせたというと大袈裟だが、せいぜい3巻くらいまとめて購入して学校に持ち込めば勝手に流行った。あとは自分が買わなくても続きを読みたい人間が買ってきて自然と全巻が流通するようになる(ただし、その古書店に全巻ある場合のみ有効)。そういうエコシステムが出来上がっていた。貧乏な中学生がお小遣いの範囲で楽しむには中古本がぴったりだ。わざわざ電車に乗って大きめの本屋で新品のラノベを買っているような人間はそれこそ本物のオタクくらいしかいなかった。あの当時はただひたすら安く消費できる作品を探していたのだ。

さて、本題に関係のない説明が多くなってしまったのでそろそろ本題に入る。中学校でラノベが禁止になった原因は全て私にあった。事情はこうだ。

まず私は友達と一緒に大きめのターミナル駅に遊びに行き、アニメイトに行った。そこで初めてラノベを表紙買いした。人生で本を表紙買いしたのは現時点でこれが最初で最後だ。とにかく面白い表紙だった。具体的な作品名を挙げるのは憚られるので説明すると、女性がパンツをかぶっている表紙だった。これは面白い。早速買って学校に持ち込んだ。しかし、それは校内で流通させるためではない。ちょっとしたイタズラのためだ。

まずその本を持って隣のクラスに行き、テキトーな人間を呼んで「〇〇にこの本を借りてたから返しといてくれ」と伝えた。しばらくした後にそいつが「なんだよこれ笑」とか言って突っ返してくる、というのが私の想定だった。その程度のイタズラができれば良かった。しかし、なんの音沙汰もないままに数日間が過ぎ去っていった。そして、その本の行方も知れなかった。流通していれば誰が持っているかくらいすぐ分かったのだが、流通しているわけでもないらしかった。本はどこにいったのだろう。

一週間くらい経ち、朝読書の時間にライトノベルを持ち込むことを禁止することが朝のHRで伝えられた。女教師は理由を伝えづらそうにしていたが、「あのー...エロい本とかを持ち込む人もいるので...」みたいな説明をしていた。あっ、俺のせいだなと思ったが、特に呼び出されたりはしなかった。イタズラをしたきり自分から反応を伺うのも野暮だなと思ってそれまで接触していなかったが、こうなっては話を聞くしかないと思って〇〇と話した。すると、彼は衝撃的な事実を語った。なんと、彼はイタズラを仕掛けたあの日、体調不良で休んでいたのだ。そもそもイタズラを仕掛けるのに出席すら確認していないとはなんたる計画の杜撰なことか。その本は彼の机に置かれ(せめて引き出しに入れておいてくれれば事は大きくならずに済んだのに...)、通りすがりの生徒が興味本位で開いては笑い、ついには担任の知るところとなったのだ。どうやら本はその担任に回収されたらしい。彼は後日登校してから責められたが、その日は休んでいたというアリバイがあったためなんとか逃れられたと言っていた。

事態が少し複雑なこともあり、私が直接の原因であることは何人かを除いて知られてはいなかった(知られていたらどうなったことか身震いがする)し、私自身もシラを切っていたために特に私が責められることはなかった。しかし、ちょっとしたイタズラのせいで最も人気の高いライトノベルが禁止されるというとんでもない事態を引き起こしてしまった。それからしばらくの間、生徒はライトノベルを読むことを自粛していた。自粛という表現を使ったのは、ライトノベル禁止を発表してはいるものの教師が何ら実効的な対策を取っていなかったためだ。一人一人が読んでいる本を検閲するようなことはなされなかった。発表から一週間も経たぬうちに、生徒はまたライトノベルを読み出した。それは当たり前だ。何のペナルティもないのだから。教師が見回りに来たときに挿絵のページを開かないようにすることくらいを注意すれば何の問題もなかった。タイトル詐欺みたいになってしまったが、結果として状況は前と何も変わらなかった。次第に私が原因だと知り始めた生徒も多いが、このおかげもあって私が責められることはなかった。

さて、あの本はどこに行ったのだろうか。あのクラスの担任の女教師の家のゴミ箱にでもぶち込まれたのだろうか。アレ以来二度と見ることはなかった。今でも覚えている。アニメイト特有の透明なビニールカバーの上から、何重にもブックカバーをかけられたあの本のことを(できるだけヤバい本に見せるためにあえてそうした)。ちなみに、その作品はそれから一年後にアニメ化が決定された。その頃にはアニメやラノベに興味がなくなっていたが、それを聞いて何ともいえぬ感慨深い感情を覚えたことを思い出す。おしまい。

2年間勤めた開発アルバイトを辞めた

2年間お世話になったバイト先を辞めた。所詮バイトだけど退職エントリというやつ。

始まり

遡るは大学2年生の冬頃、1年弱勤めた家電量販店のバイトを前年度の末に辞め、必死に開発系のインターンを探していた。本当はもっと早くから開発系の仕事をしてみたかったのだが、大学1年時は色々あってそれどころではなかった。この暗黒期を詳しく語るつもりはないが、とにかく家電量販店でのバイトは自分にとって社会復帰のような役割を果たしてくれた。バイトしながら金を貯め、プログラミングの勉強もし、Webサービスを自作したりしてある程度プログラミングに慣れることができた。これで準備万端というところで家電量販店のバイトを辞めた。(年末商戦で大量のお客さんが来るのが億劫だったのも理由の一つではあったりする。)

さて、そこでインターンを探し始めたのだが、結果から見るとこれは失敗だった。当時の自分はインターンと聞くとバイトと変わらないようなもので時給がきちんと出るとばかり思っていたのだが、現実はそうでもなかった。基本は無給で交通費のみ支給、戦力化基準を満たしたら賃金が発生する、というようなところが多かった。これは私が探したところがそういうところばかりだったのか、一般的にそうだったのかは分からない。しかし、そうした認識のズレがあり、インターンは長続きしなかった。やりますと言った次の出勤日当日に電話をかけてやっぱり辞めますと言ったり、あるいは無限に続くかに思われた研修に嫌気がさして飛んでしまったり。本当に申し訳ないことをした。ごめんなさい。

こうした失敗を通して、確実に給料が出るバイトをメインで探し始めることにした。当時からエンジニアとして就職することを意識していた私には、そこでの経験が就活に活きるかどうかも重要であったため、この選択には一抹の不安があった。一般的にはインターンの方がバイトより受けが良いような気がしたからだ。専攻が情報系とかけ離れている、ましてや文系の私にとっては就活の成否を決定すると思ったからだ。まあ、後から思えばインターンだろうがバイトだろうが開発経験には違いがないため、そこまで神経質にならなくてよかった。

Indeedで「Ruby バイト」と検索(Rubyは当時の私が唯一まともに使えると言って良いプログラミング言語だった)、出てきた会社をリストアップし、良さそうなところに決めた。 すぐに折り返し連絡が来て、面接の日程を決めた。勝手がわからなかった私はスーツで行った。オフィスはマンションの一室にあり、はっきり言って怪しい雰囲気が漂っていた。チャイムを押して挨拶をすると、社長に困惑されながら「えーと、バイト希望の人でいいんですよね?」と言われた。Web系は私服で行くべきだったらしい。ちなみに、それ以降就活も含めて私がスーツを着たのはこの一回きりだった。 面接ではコーディングテストが課された。あとは数学の文章題。これには驚いた。コーディングテストは予想できていたが、まさかの文章題とは。焦って頭が真っ白になったが、SPIで出てくるような数学の問題だったので落ち着いて考えれば解けた。その場で採用を通知された。 帰り際、「あ、忘れてたけど時給は〜円です。」と言われた。時給が出るのが何より嬉しく、安心した。

それから

入社後の研修は手厚く、最初に始める開発バイトとしてなかなか良い環境だった。バイトを多く受け入れているようで内容も充実しており、研修が終わるとそのままスムーズに業務に移行できた。また、何より嬉しかったのはスッと働けることだ。どういう意味かって?出社したらおはようございまーすと挨拶をして、PCを開いて作業を開始できることだ。出社したらまず着替え、食堂で時間を潰し、タイムカード打刻の列に並び、10時キッカリになったら大きな声で「本日も一日、笑顔で明るく元気よく〜」などと言って打刻し、「接客9大用語、いらっしゃいませー!ありがとうございます!おそれ...」などと唱和をする必要がないということだ(これでどこで働いていたかバレてしまったかもしれない)。でもこれはこれで案外楽しかった。人生は経験だ。色々と勉強になったし、このくらい厳しい方が当時の自分を叩き直すには良かった。

バイトでは色々な業務をやった。スクレイピングをやったり、名寄せをしたり。一番長くやっていたのは自社サービスの開発だった。また、その一貫としてSQLのクエリチューニングなんかを熱心にやっていた時期もあった。後述するが、この経験が後の就活であそこまで役立つことになるとは思わなかった。

就活

Web系の就活は早い。就活は大学3年生の秋頃から始めた。翌年の1,2月にはもう内定を決めて身を落ち着かせたいということでバイトの出社頻度を減らし、就活に集中できるように調整してもらった。その時に社長にアドバイスしてもらったことは今でも覚えている。 「成長してる会社に行った方がいいですよ。失敗してる会社に行くと自分の価値まで低く見られてしまう。地銀の人とか転職しようとしてる時に苦労してるでしょ。あとはちゃんと利益を上げてる会社。よくAIベンチャーとか一時取り沙汰されましたけどね、ちゃんと利益が上がってる会社って一握りなんですよ。そういう評判とかに騙されずにちゃんと利益を積み重ねてるところに行った方がいいです。」 というようなアドバイスをもらった。にわか仕込みの知識でも会社の決算資料なんかをざっくりとでも読んでおくのは大事かもしれない。就活中はできていなかったが、就活後になってこのアドバイスを思い出して簿記2級の資格を取ったりした。

さて、1月には就活を終えた。その当時は前述したクエリチューニングの仕事をメインでやっていたためアピールに使っていたが、これがなかなか刺さった。おそらく、自分が受けている企業では何らかの形で開発の実務経験がある学生は珍しくないだろう。しかし、その中でもクエリチューニングというのはなかなか経験しにくい仕事なのではないかと思う。大した専門性も際立った能力もない自分のような人間が唯一差別化できたとしたらそこだった。その証拠にこのエピソードを一次面接で出して以降、最終面接を含む全ての面接で「クエリチューニングの話を聞かせてください。」と言われた。

そして

そして現在こうしてブログを書いている。あのエピソードのおかげ(?)もあって、配属先はデータ系の部門になった。就活の合否から配属先までを一挙に決定してしまうくらい強力なエピソードだった。というかほぼこれ一本で就活したと言っても良い。

今でもたまに考えてみることがある。大学一年生の時に家電量販店のバイトを始めていなかったら、今のバイト先に出会えていなかったら。自分はどうなったんだろうと。悪く見えていたら私の書き方が悪いのだが、家電量販店のバイトは腐りかけていた自分を真人間に戻してくれた。あれがなかったら自分は毎日不眠と動悸に悩まされ、大学と自宅を往復するだけの生活だった。 そこでの経験を通してまともに働けるようになり、体調もある程度落ち着き、今のバイト先にも出会える結果となった。あれが全ての起点だった。陽が落ちかけた夕闇の中、布団にこもりながらスマホで求人情報を探し、恐る恐る電話をかけたあの日の勇気を称えたい。

別にここから「みんなも勇気を出して一歩踏み出そう!」ということが言いたいわけではない。ただ、自分が今こうしてエンジニアとして就職するという数年前の目標を無事に達成できているのは、偏にその場その場での選択と、そこから発生した出会いや環境の変化のおかげだ。こうした良い出会いや変化を加速させる仕事がしたい。 そして、将来的には一から事業を作って育てていきたい。ひとまず入社先でデータを眺め、データと向き合い、色々と考えたい。

ここまでバイト関係ない身の上話も多くなってしまったので最後に。 「席は開けておくのでいつでも戻ってきて良いですよ。」と社長に言ってもらえたのが冗談でもお世辞でも嬉しかった。

2年間本当にお世話になりました。ありがとうございました。

Haskellで選択ソート

Haskellのお勉強がてら簡単なソートアルゴリズムを実装してみる。

選択ソート

配列の中から最小の要素を探して、左側にぽいぽい置いていくアレ。通常の言語では配列を使って値をスワップしていく処理を書くことになるが、Haskellでは当然リストの状態を変更することなど許されない。 ということで値をスワップせずに実現する必要がある。 ※最初に断っておくが、初心者が学習用に書いているもので何の最適化も施されていないし、コードが冗長であったり非効率であることはご愛嬌である。

問題を分割する

「困難は分割せよ」とは国語の教科書のルロイ修道士の発言。選択ソートは大きく分けて2つの処理からなっている。

  1. 最小値を発見する。
  2. 最小値の要素と、ソート済みでない要素の中で一番左にある要素を入れ替える。

Haskellでは2が素直に実装できないことはさておき、1の最小値を見つけるコードから書いていく。(あ、minimum関数の存在は知ってます。再帰のお勉強のために独自実装します。)

searchMin :: [Int] -> Int
searchMin (x:xs) = if length (x:xs) == 1
                   then x
                   else if  x > head xs
                     then searchMin xs
                     else searchMin (x:tail xs)

配列の要素を順に見ていく場合、他の言語ではイテレータを回すのが基本だが、Haskellでは再帰を使用する。ここでやっていることはリストの先頭の要素とその次の要素を比較。前者の方が大きければ前者を除いたリストをseachMinに渡す。後者の方が大きければ後者を除いたリストをsearchMinに渡す。これを繰り返していくと再帰が深くなるごとにsearchMinの引数として渡されるリストの要素数は減っていく。最終的に残った一つが最小値であるため、if式でリストの要素数が一つになったらそれを返すように書いている。

とりあえず関数を作ってテキトーなリストを渡してみる感じ上手くいっている。ヨシ!(現場猫

さて、最小値を見つけるのは十分できる。鬼門は次だ。他の言語であれば最小値の要素の添字とソートが済んでいない要素の中で一番左の要素の添字(これはそのままイテレータの変数を使うのが普通)を取得して値をスワップすれば話は済む。しかし、Haskellではリストの値を文字通りスワップすることはできない。[1,2,3]を[3,2,1]にしたかったら[1,2,3]を変換した新しいリストを作る必要がある。

selectionSort :: [Int] -> [Int]
selectionSort (x:xs) = minNum:(selectionSort restArr)
  where minNum = searchMin (x:xs)
        restArr = delete minNum (x:xs)
selectionSort [] = []

ということでこんな感じになった。与えられたリストから最小値を見つける→その最小値を除いたリストを生成する→そのリストの最小値を見つけるを繰り返していく。効率はさておき、原理的にはしっかりと選択ソートになっているはず。ちなみに、一般的に選択ソートは安定ソートではないが、この実装だと安定ソートになる。 Wikipediaの安定ソートのページに載っている[1,2a,2b]の例だと、スワップを行うために2a,2bの順番が崩れてしまうが、この実装ではスワップを行わないため最小値として1が取り出された後の並びは[2a,2b]のようになり崩れていない。

高速化

もう少し高速化できないか探していたらこちらのブログを発見した。どうやらunfoldrを使った実装の方が早いらしい。 せっかくなので自分のコードとの実行速度をtimeコマンドで比較してみた。ロジック自体の比較のため、独自実装したsearchMin関数はminimum関数に置き換えた。(ちなみに独自実装だと死ぬほど遅かった。)

テキトーに直積を使って30000個の数字からなるリストを作成し、ソートしてみる。

自分のコード

real    0m15.321s
user    0m15.241s
sys     0m0.080s

unfoldr仕様版

real    0m24.088s
user    0m24.077s
sys     0m0.010s

あれ、unfoldrを使わない方法実装の方が早かった。なんで? もしかしたらこの記事が書かれている頃のHaskellと現在のHaskellでは最適化の方法が異なるのかもしれない。 原因をご存知の有識者の方がいらっしゃいましたらぜひともご教示お願いします。

それでは!

Haskellでスクレイピングしてみた

資格勉強が終わったので久々に呑気にプログラミングをしている。もう後は入社を待つだけみたいな状態なので、喫緊で勉強しなければいけないことも特にない。業務で使う技術は業務で学べば良いし。 ということで、分厚い技術書を写経するだけで終わっていたHaskellに挑戦している。やはり何かしら動くものを作らないと技術の習得は難しい。かといって何を作ろうかと悩んでいたが、とりあえずスクレイピングでもしてみるかと思い立った次第である。スクレイピングならHTTPライブラリとHTMLのパース用のライブラリさえあれば良いし、結果もすぐに返ってくる。成功したかどうかも分かりやすい。しかし、Haskellの壁はなかなかに高かった。

ライブラリ選定

まずはライブラリ選定である。Haskellではライブラリを探す際はHackageというサイトから調べるのが良いらしい。なかなか検索体験が良い。

https://hackage.haskell.org/packages/browse

「http」と検索すると、http-clientとhttp-conduitがどうやらそれらしい。どちらにするか迷ったが、別に複雑なリクエストを送るわけでもないのでhttp-conduitのNetWork.HTTP.Simpleを使うことにした。

次はHTMLのパースライブラリだ。「html」で調べると、html-conduitというものが出てきた。これはどうやらHTML文字列をDocumentと呼ばれる型に変換してくれるらしい。そしてそのDocumentに対していろいろとと操作するにはxml-conduitが必要らしい。ということでこの2つを入れた。

実装

一気に作業してしまったので、ここまでの思考過程は省略する。出来上がったコードがこんな感じ、変数名はテキトー。

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Lib
import Network.HTTP.Simple
import Text.HTML.DOM
import Text.XML.Cursor

main :: IO()
main = do
  request <- parseRequest "http://example.com"
  res <- httpLBS (request)
  let doc = parseLBS $ getResponseBody res
  let root = fromDocument doc
  let cs = root $// element "p" &/ content
  putStrLn $ show cs

これでpタグの中身のテキストを取り出すことができた。しかし....

はっきり言ってよく分からない。 型に注目して一つ一つ処理を追っていきたい。

 request <- parseRequest "http://example.com"
 res <- httpLBS (request)
 let doc = parseLBS $ getResponseBody res

ここは別に良い。parseRequest関数でURL文字列を指定し、Request型が返ってくる。それをhttpLBS関数に引数として渡す。 httpLBS関数はRequestを引数にとってResponse ByteStringを返す。これはResponseのコンテキストにあるByteStringと解釈できる。 ちなみに同じ型シグネチャでhttpBSという関数もある。名前の通り、httpBSは通常のByteString、httpLBSはLazy ByteStringを返す。 ByteStringもLazyByteStringも型としては同じByteStringなのか、どうやって見分け付けるんだろう...。(初心者並感) 次はgetResponseBodyでResponseコンテキストからByteStringを取り出し、parseLBS関数でDocumentを取り出す。 ここまではシンプルで非常に分かりやすい。なんだこんなものかと思ったが問題はここからだ。

let root = fromDocument doc

fromDocument関数はCursorという型を返す。なんだこの型は...。 xml-conduitにちゃんと説明があるので読む。

hackage.haskell.org

要約: Cursorは単一のノード、およびそのノードの場所を示すよ。自分の親、兄弟の場所も知ってるよ。

つまりこのノードを使って目的のノードの場所を探索していけば良いらしい。となると、rootが示すノードとは何だろう。 恐らく、rootのノードを示すということは<html>になるはずだ。ちょっと見てみよう。

elementNamen :: Node -> Name
elementNamen (NodeElement e) = elementName e

main :: IO()
main = do
  request <- parseRequest "http://example.com"
  res <- httpLBS (request)
  let doc = Text.HTML.DOM.parseLBS $ getResponseBody res
  let root = fromDocument doc
  let rootNode = node root
  putStrLn $ show $ elementNamen rootNode

これで合ってるかは分からないが、Cursorの中身をかっさばいてNodeを取り出し、それに対してelementNameという関数を適用してみた。elementNamenというアホみたいな命名はご愛嬌。

結果はこちら。

Name {nameLocalName = "html", nameNamespace = Nothing, namePrefix = Nothing}

nameLocalNameがhtmlになっている。恐らくこれがタグの名前を示すということで、やはりhtmlタグのはずだ。 ここまでは理解できた。Document型からhtmlタグを示すノードを取り出したのだ。

let cs = root $// element "p" &/ content

ここが鬼門だ。ネットに転がってるコードを参考にしたのだが、処理はよく理解できていない。 パっとコードを見た感じではやってることは分かる。rootに対してpタグを探してそのテキストの中身をcontentで取ってきている。 実際にどんな処理が行われているのかを調べるために、まずはこの式を定義にそって分解してみる。

descendant root >>= (element "p" >=> child >=> content)

定義を見ると、$//と&/はどちらもinfixr 1 が指定されている。これは右結合の演算子で、優先度が同じだということだ。今回の例では&/から先に評価されるため、上のコードでは右オペランドをかっこで括ってある。 さて、上の式を順に見てみる。

descendantはAxis型(Cursor -> [Cursor])なので、そこにroot(Cursor型)を適用することでCursorのリストが返ってくる。名前の通り、このCursorのリストはrootノードの子孫ノードの集合だと分かる。 左オペランドはCursorのリスト。では、右オペランドはどうなるか。 それぞれ型シグネチャはelement "p"はAxis, childはCursor node -> [Cursor node] (これはAxisとは違うのか?), contentはCursor -> Textとなっており、これらを>=>で繋いでいる。

この演算子モナドに定義されていた。

hackage.haskell.org

(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c

'(bs >=> cs) a' can be understood as the do expression

do b <- bs a

cs b

そういえばMonadの定義に必要な関数に>>=(bind)があった。>=>は、あれと同じ要領で順繰りに処理をつないでいくためにあるようだ。 つまり、引数に対してelement "p", child, contentの順に処理が行われていく。 型シグネチャは以下のようになっている。

:t (element "p" >=> child >=> content)
:: Cursor -> [text-1.2.4.1:Data.Text.Internal.Text]

Cursorを引数に取り、その中からpタグのノードを取得し、それらの子要素のテキストを抜き出すという処理だ。なぜpタグからではなくpタグの子要素のテキストを取ることになっているのか。それはpタグの中にテキストが入っている場合、pタグの子要素としてNodeContentというものが入っており、そこにテキスト情報が入っているからのようだ。 では、ここで右オペランドの関数の引数に渡されるCursorとは何か。これが左オペランドの[Cursor]だ。 右オペランドの関数で要求する引数の型はCursorだが、左オペランドは[Cursor]となっている。これを上手く繋ぐのが >>= 演算子だ。 これにより、リストモナドのコンテキストで関数を適用し、最終的にテキストのリストが得られるということだ。

ま、モナドの理解が足りないよね

この記事を書くのに入門Haskell本のモナドの章を復習する必要があった。Cursorを引数に取る関数になぜ[Cursor]を渡せるかよく分からなかったからだ。理屈を理解してみると、なかなか便利な機能だなあと思う。モナドそのものが何なのかはよく分かっていないが、少なくともこの仕組みを使えばモナドという特殊なコンテキストを表す一部の型について、わざわざラッパーを作らずともモナドを引数に取らない関数を適用することができる。リストをあたかもリストじゃないかのように扱う、今の私の頭では理解するのが難しいがとんでもなく強力な機能だということは分かる。なんにせよ関数型言語は一般的なオブジェクト指向や手続き型の言語とは異なるパラダイムなので、コードを数書いて慣れていくしかなさそう。頑張る。

2021年の振り返り

2021年をざっくり振り返る。

1月

就活が佳境の時期だった。昨年の10月から就活を始めたが、この頃には自分が何をやりたいかがある程度定まってきて選考を受ける企業もかなり絞れてきた。その中でも初期に選考を始めた企業でちょうどその軸にマッチしていた企業があったので、そこの選考に全力を注ぎつつ保険として同じようなタイプの企業の応募を始めていた。幸いにもそこの最終選考に通ったので、これ以上就活を続けたくなかった私は内定を承諾、就活を終えた。自分としても満足する内定で、これ以上就活にリソースを割かなくて良いということで肩の荷が降りる気持ちだった。

2月

カレンダーを見返しながら書いているが、この時期は予定があまり入っていない。就活を終えたのでやることもあまりなかったのだろう。手元の紙の手帳を見ると、どうやら簿記3級の勉強をしていたらしい。25日には試験を受けている。記憶が曖昧だが、就活終わりと同時に勉強を始めたっぽい。確かに、暇になった人間が簿記を始めとした資格勉強を始めるというのはよくあることだと思う。自分の友人のニートも筋トレや簿記をやっている。何もしていない人間は、日常の中に何かしているというマイルストーンを欲している。自分もその例に漏れなかったらしい。 簿記の勉強を始めた目的としては、就活を通して企業の決算報告資料とか財務諸表とかを読めるようになったら便利だなあ、くらいのものだったと思う。まあ取っといて損はないのでよかった。商学部だし。

3月

バイトで稼いだ金で歯列矯正を始めた。今現在(2021/12/31)ではほとんど終わっている。なかなか良い選択だったと思う。ただし、片側50マンかかり、バイトで貯めたお金をごっそり持っていかれた。来年から一人暮らしを始めたいので、資金を貯めるために来年の2月一杯まではバイト先にお世話になろうと思う。あと、この頃から簿記2級の勉強を続けて始めたっぽい。どうやら本当にやることがなかった模様。学校の授業ももちろんあったが、単位はほとんど取り終わってる上に全てオンライン授業なので時間があった。

4月

楽天カードを契約した。ポイントカードとか色々あって面倒なのでここから楽天経済圏に突入している。現在はコンビニでの買い物は楽天ペイ、本は楽天ブックスで買っている。

5月

教習所に入校する。周りの友達にMTで取っている変人が多かったのでそういうもんなんだと思い、地元の友達と一緒にMTを選択、東北某県へ免許合宿に行った。なんだかんだ人生で初東北だったかもしれない。個人でも家族でもあまり旅行をしてこなかったので、自分の中の日本地図はかなり狭い。
合宿した場所は盆地なようで、昼夜の寒暖差が激しく、5月なのに夜は気温が一桁まで下がった。S字だとかクランクだとかより、この寒暖差で体調を崩して熱を出して、コロナ対策として強制送還になるのが一番怖かった。こちとら親に免許代を出してもらうようなゆとりキッズではなく自費だ。冗談じゃない。なんとか延長なし18日程度で帰宅できた。一緒に来た友達は卒検で優先車妨害×2(しかも一回目で助手席のブレーキを踏まれてるので本来は一発アウト、温情をかけられながら2回目もやってみせた)、三速で発進しようとしてエンストを5回くらいした末に落ちた。教官の「あのー君ね、もういいよ」の一言は忘れない。あの時の車内の雰囲気は22年間の人生の中で一度も味わったことがなかった。

6月

あまりイベントはない。内定先で必要になる個人情報保護士という資格の勉強、取得をした。この資格は基本的に暗記だけしていればいいから楽な上に、セキュリティの分野に少し絡むところがあるのでエンジニアにとってはそこまで苦ではなかった。一番辛かったのは勉強というより試験時間だった。途中退室、トイレ退室なしで2時間半。4択100問の形式なので時間は余る余る。膀胱耐久の資格といっても良い。

7月

田舎に住んでる友人のところへ遊びに行った。地元のおばあちゃんが一人でやっている居酒屋に行った。帰るときに横で飲んでいたお兄さんに「にいちゃん達の分は奢ってやるよ」と全額奢ってもらった。田舎はすごい。そのあとは夜の海を眺めながら缶の酒を飲んでいた。横浜の内陸の方でずっと暮らしてきた自分にはどうも落ち着かなかった。(この記事の画像はその夜の海を映したものだ。何も見えない。) ちなみに、この時は哲学書にかかっていたので資格の勉強とかはしていなかったように思う。夜の海を眺めながら哲学論議をしていたら終電がなくなっていた。翌朝、なんとか地元に帰ることができた私は、最寄り駅のトイレで緑×オレンジ色の吐瀉物を射出した。

8月

内定者ハッカソンをやった。優勝して景品(技術書とノイズキャンセリングイヤホン)がもらえた。チームに恵まれた。

9月

何もやってない。強いてあげるとするならば、とある哲学書を読んで労働の意欲を失っていたのが復活した。その契機となったのはニーチェの本だった。ざっくりとまとめると、醜いルサンチマンを持つな、自己を超克しろ、みたいな内容だった。なるほど本能を否定するような言説ばかりに囚われていた自分には耳が痛かった。成功者を僻むのはやめよう、ニーチェの言う力への意志を持とう、というポジティブな方向に意識が変化した。今まで前澤社長があまり好きではなかったのだが好きになった。

10月

前々からちょこちょこ家で筋トレはしていたが、本格的にジムに通い始めた。ついでに簿記2級の勉強も再開した。自分で振り返っても、これは明らかにニーチェの影響だったと思う。数ヶ月越しに簿記と筋トレというニート二種の神器を取り戻した私だが、中身は着実に進化している。筋トレはジムでする本格的なものに、簿記は2級になっている。心身ともに自らを超克していこうという崇高な意志だ。

11月

前月とほぼ同じ、簿記と筋トレ。変わったのはベンチプレスを始めたことくらい。

12月

現在。28日に簿記2級を取得した。再開してから数えると3ヶ月、勉強期間としては上々だろう。

さて、ここまでカレンダーアプリと手帳を元に振り返ってきた。目に見える成果としては資格、見えない成果としては前向きな意識(なんか浅い)を得られた。あまり書くことがない月もあったのでもう少し頑張れたかなあと思う。そして、書いていて思ったが、技術的なことについての記述が特になかった。まあカレンダーベースで見ているので多少は仕方ないが、それにしても前年と比べてあまり技術の勉強はできていなかったと思う。技術的な変化については思いつく限りで列挙すると

  • Crystalを始めた(このブログもCrystal製、UIがしょぼいのはバックエンドマンなので許してほしい)
  • CrystalでOSS開発を始めた。
  • VSCodeからVimに乗り換えた。こちらを参照

せいぜいこれくらい。ま、再来年から頑張ろう。

所感

振り返りはここまでとして、現在の所感をなんとなく綴る。この一年を通して、人生って思ったよりあっさり終わるんだろうなあと思った。前に一緒に飲んだ友達も同じようなことを語っていたのでちょうどそういうことを感じる年頃なのかもしれない。「一人暮らしで家に帰ったときに一人で、中年になってもこれじゃまずいと思ったから早く結婚相手を探さなきゃ」と、そいつは別に結婚相手に困るようなスペックでもないのにそんなことを言っていた。それが、自分には人生の畳み方を考えているように思えた。人生は思ったよりも早いという点では一致しているのだが、自分はだからこそ自分の人生を賭けてやる価値のあることを探そうと思っている。自分で事業を始めるのでも良いし、何か面白いことをしようとしている人の中に参加するでも良いし。とにかく今は、というより社会人になってしばらくはそうした時に役立てる力を身につけたいと思っている。30歳になっても内定先の会社にいたままなら私の負けだと考えて良い。

来年の目標

人と会って、いっぱい話して、知見を広げたい。

さて、つらつらと駄文を弄したがここまでにしようと思う。皆様、良いお年を。

VSCodeからVimに乗り換えた

※この記事ではVimに移行した経緯についてのみ書く。具体的なVimの設定等については別途技術記事として書くつもりだ。

最近、
VSCodeからVimに乗り換えた。その理由の一つ一つを明確に挙げることはできないが、恐らく「かっこいいから」が最も適切な気がしている。TwitterVimmerVimの話題で盛り上がっているたびに、イケてるWeb系企業のプログラマVimを使ってライブコーディングするのを見るたびに、その思いは日増しに強くなっていった。私もああなりたい、と。もちろん、他の多くのプログラマがそうであったように、私もVimmerになることを志し、そしてあっさりと挫折した経験がある。Vimは難しい。Vimは決して使用者に媚びず、むしろ使用者の側からVimに染まることを要求してくる(これはVimmerの狂信性を思えば理解に難くない)。そもそも、初見で全く動かすことができないのは常軌を逸しているのではないか。駆け出しの頃にGitを使っていたら何かの拍子にVimが開いてしまい、必死に検索して四苦八苦しながらエディタを閉じた経験があるのは私だけではないと思う。このことから私のVimの第一印象は最悪であった。さらに当時は既に優秀なGUIのエディタが存在していたため私がVimを選択しなかったのは至極当然なことだろう。その時は確かAtomかなんかを使っていた。そして次にVSCodeに移行した。このどこかでVimにも挑戦して挫折した。もうこのままVSCodeでいこう、と思っていた。

「ダサい」指さばき

私は東京にあるベンチャーで一年半ほど開発のアルバイトをしており、主に自社サービスの開発に携わっている。一年半もいれば新しくアサインされた新人さんの質問対応をするようにもなる。そして、そこで考えさせられる出来事が起こった。
新人さんのバグフィックスを手伝っていた時である。「ここの記述をこうすればいいんじゃないですか。」と特定の記述の修正を提案した。そこで、その方はVSCodeを使っていたのだが、矩形選択を使って記述を直し始めた。同一の記述が並んで二行、さらに一行飛ばして下にも同じ記述があったので、その三箇所を同時に選択して修正していた。この時は私は非常に感心した。それは以下の理由からである。
まず一つが、全てをキーボード操作で行っていたことである(私はVSCodeで矩形選択するのに、Shift+Altを押しながらトラックパッドを操作していた)。次に、行を飛ばして同一の箇所を選択していたことである。これはシンプルにどのように実現しているのかよく分からなかった。調べたところ、マルチカーソルというVSCodeの大きな特色とも言える機能らしかった。しかし、私はそれを知らなかったのだ。

私は恥じた、キーを押しながらトラックパッドで矩形選択する己の指さばきの隠しようもない「ダサさ 」に(もう一つ恥じるべきはVSCodeを使っていながらその主要な機能も知らないエディタへの無知・無関心だが、この時は特に気にしていなかったように思う)。 そこで、「かっこいい」指さばきを志した。基準は簡単。トラックパッドをベタベタ触ればかっこ悪い、キーボードだけで完結すればかっこいい、だ。その週の休日から、私は家のデスクトップPCでVimの練習を始めた。もちろん、VSCodeのショートカットを覚えるという手もあっただろう。しかし、VSCodeは腐ってもGUIだ。VSCodeの機能はトラックパッドを使うことを前提に最適化されている。マルチカーソルもトラックパッドを使う方がやりやすいし、Gitのコンフリクト解消などもポチポチ押すことを前提として作られているだろう。そもそも全ての操作にキーボードショートカットが割り当てられているかも分からない。となると、VSCodeを使って実現できるのは「できるだけトラックパッドを触らない」状態だ。たとえ上手くやったとしても、私が定義したところのダサさの成分は残る。
ということで、必然的にVimを習得することにしたのだった。

CLIは「かっこいい」

CLIGUIについても言及しておきたい。私はCLIが好きだ。そもそもプログラマを目指した原体験に、「黒画面、緑文字のターミナルに文字を打ち込む、映画に出てくるようなハッカーへの憧れ」があるからだ(実際に私のターミナルの色はその通りになっている)。ということで、私はできるだけCLIで色々なことを行うようにしている。と、思っていたが、その実エディタはVSCodeなのだった。こだわりはせいぜいGit操作にsourcetreeを使わないくらいだ。
しかし、私がGUIをあまり好まないということは確かだ。GUIのアプリケーションを開くとメニューが並んでおり、さらにそのメニューの中にも色々な項目があり...嫌気がさす。それは私がそのように配置したものではない。いきなり他人の部屋に連れてこられたようなもので居心地が悪いのだ。結局はその中のいくつかの機能を使うことになるが、使わない機能についてもいちいち目にしなければならない。そこで暮らしていながら開けていない部屋や物置がたくさんあるようなものだ。必要なものだけ手元に置いて、またさらに必要なものがあれば探して手元に置いて、自分が勝手を知っている自分の部屋にいるのが一番良い。という事で、私はVimで自分の部屋を作ることにしたのだ。
余談だが、私は同じ理由でソーシャルゲームもあまり好きではない。初めたはいいが、ショップやらストーリーやらバトルやら設定やらの大量のメニューを見せられるともう何から手を付けていいか分からなくなってやる気がなくなる。

Vimは楽しいものだった

さて、私は現在このブログをVimで書いている。一回挫折しているおかげで基本的なキーバインドは理解していたので、Vimの急激な学習曲線をなんとか乗り越えることができた。プライベートの開発でもバイトの開発でももっぱらVimを使用するようになった。VSCodeはアンインストールはしないまでも、MacのDockからは姿を消している。colorshemeを変えて気分転換したり、プラグインを吟味したり、設定を模索したり、vimrc(私はneovimを使っているので正確にはinit.vim)を整理したり。あの日の挫折が嘘のように、それなりにVimを楽しむことができるようになった。私がVimを使い始めた時はプログラミング自体を始めてから数ヶ月程度しか経っていなかったため、そもそも根本的な部分の知識が不足していたことが挫折の原因として大きかっただろう。自分が何をやっているかを自分で理解できるようになってからは、驚くほどVimを楽しめるようになった。
また、Vimを使うことで自分の作業効率についても意識できるようになった。これはVSCodeでは得られない視点だった。自分が使う道具についてより多くを把握し、効率化できているかを考えることは、プログラマに限らず何かを"作る"職業においては重要な姿勢だ。それを身につけることができたVimには深く感謝している。これからも長く使い続けるつもりだ。