Classi株式会社に入社しました

今月からClassi株式会社で働いています。まだ試用期間なのですが、所属を明かして良いと許可をもらったので入社エントリ書きます。

前職を退職しようと決意してから(ここにはかなりの葛藤があったのですがそれはまた別の話)、転職エージェントにお世話になりつつさまざまな会社を訪問させていただきました。

わたしが転職に際して重視したのは以下の三点でした。

  • 家族が幸せにごはんを食べていけるための給与
  • 自分のやっている仕事が世界を良くするであろうと自分が思えるかどうか
  • 自分の得てきた能力が求められていて、なおかつ転職先できちんと成長できそうか

幸運かつ大変ありがたいことに、これらの条件を満たしてくれるような多くの会社からお声掛けをいただけたのですが、Classiに入社することを決めた決め手は以下の2点でした。

  • 教育のセンターピンとも言える学校教育をビジネスドメインとしている
  • 面談中にメンバーのことを好きになってしまった

わたしは教育に関してはけっこう強い思いを持っていて、そのあたりの話は過去のエントリにも書いているので繰り返しません。

Living in Peaceの「チャンスメーカー奨学金」の支援者になった - 猫型の蓄音機は 1 分間に 45 回にゃあと鳴く

子供にとって一番長い時間を過ごす場所である学校を対象として、そこで起こっている問題に取り組んでいるClassiは、数あるEduTechの中でも、困難でなおかつとても意味のある仕事をしていると感じたのが入社を決めた一つ目の理由です。

二つ目の理由である、メンバーのことが好きになったというのは、ちょっと書くの恥ずかしいですね。転職活動中、たくさんの会社にお伺いしたのですが、その中でもClassiには何度も面談に来ていて、面談するメンバーが違っても、毎回一貫して「相手も自分も尊重する」という姿勢を感じました。

一例を挙げると、最初から面談の時に自社が現在抱えている問題や「ここはもしかしたらストレスになるかもしれない」というようなことを包み隠さず誠実に伝えてくださったことや、自分たちが大切にしている価値観についてご説明いただいた上で、わたしの持つ価値観についても丁寧にヒアリングを重ねていただけたことなどがあります。けど、それ以上に「終始心地よい距離感で接してくださった」という感覚があり、これは自分たちの価値観を尊重した上で他者の価値観も尊重するからこそ出てる距離感なのだろうと思いました。

そんなわけで、入社する前から「このひとたち好き〜」ってなっちゃったっていうのがあります。とくにCTOのささたつさんとお会いしてお話しできた時に「このひとがCTOならぜったいに良い文化の会社だよな」と思えたことが大きかったです。

ソフトウェアエンジニアとしてなにを期待してもらえていて、なにをしていくのかということについては、これから結果で語っていくべきことだと思うのでここでは触れません。きちんと語れる結果を出していけるように精一杯頑張ります。

恒例のあれはこちらです。

最近の音楽周り

聴く方

新しく聴いてる中でグッときたのは fusq 「Polarity」とかノンブラリ「SOUND TRACK」とか。

www.nombrari.jp

fusqはGoogle Play Musicをdigってて見つけたやつ。最近っぽい音だなという印象がある。最近こういう方面は質のいい音楽ばっかりで、聴くのが追いつかないなあって感じがしてる。そんな中でもこれはけっこう何度も繰り返し聴いてる。

ノンブラリはなにかで偶然に耳にして、それからアルバムをiTMSで買ったのがたぶん2年くらい前?で、去年のりんご音楽祭に来てたから朝イチのライブを観た。すごい演奏うまくて、ぼく的にはスタジオ音源よりもグッと来た。で、最近新しいアルバムが配信に来たこと知って、聴いたらやっぱりよくて、これも最近よく聴いてる。

新しく買ったやつはそんな感じ。けどじつはこれ書いてる今聴いてるのは昔から聴いてるやつで、パステルズの Illumination。

Illumination

Illumination

パステルズはフリッパーズ・ギター経由で知ったんだけど、そんなに一生懸命聴いてるわけではない。んだけど、このアルバムはなんかずっと(もう10年以上になると思う)飽きずに聞いている。押し付けがましくなくて、スッと「そこにある」って感じでずっと聴ける不思議な作品だなと思う。これ聴いてて音楽の記事書きたくなって書いてる。

やる方

新しく友達になったわたるくん の誕生日プレゼント企画のトリビュートアルバムに参加したり、相変わらず宅録したり。自作もので最近よくできたなと思ってるのはバターと黒胡椒という曲で、ボーカルがないところが気に入ってる。じぶんの歌があまり好きじゃないから(笑)。

soundcloud.com

あとは、よくソロで歌っておきながら自分で歌ってる音源がなかった「季節」って曲も最近録音した。あえてシンプルに録ったのがいいほうに転がったかなって思って、これもけっこう自分で気に入ってる。

soundcloud.com

ソロとしての活動は、9/1に荻窪アルカフェってお店で弾き語りライブ的なやつをやるので、興味があったら是非いらしてください。お店に予約入れていただくとぼくが喜びます。

ソロだけじゃなくてバンドでも久々にライブが決まっていて、三鷹おんがくのじかんというハコで、9月23日17:00開場、17:30〜開演という感じです。友人各位にはこちらからお声掛けもしますが、友人じゃなくてもぼくの音源やバンド音源(SoundCloudのアカウント貼っておきます)に興味を持ってくださいましたから、ぜひいらしてください。オープンで明るい、怖くないイベントです。

soundcloud.com

Scalaのパターンマッチでの@の挙動

List(1, 2) match { case Seq(xs @ _*) => println(xs) } の意味が果てしなくわからないんだけどなにこれ

という声を聴いた。たしかにScalaのパターンマッチにおいて @ の挙動はわかりにくいかもしれない。

Scalaのパターンマッチでは、@を利用して2回変数束縛を行うことができる。

たとえば@を使わないパターンマッチの例としては

Option(1) match {
  case Some(x) => x * 2
  case None => 0 
}

// => Int =2

といったものが考えられる。今はSomeの中身をxに束縛したが、@を使うことで、中身をxに束縛しつつSome自体も別の変数に束縛する、というようなことができる

Option(1) match {
  case s @ Some(x) =>
    println(s)
    println(x)
  case None => 
    ()
}

// Some(1)
// 1

簡単にいうと、「ふつうなら一回しか変数束縛できないけど、@を使うとチャンスが2倍!!」みたいな感じ(後述するが、これは正確な説明ではない)。

「変数束縛が2回できてお得でっせ!」というわけで、意味はないが、同じ値を複数の変数に束縛することもできる

1 match {
  case x @ y => x + y
}

// => Int = 2

また、case節のトップレベルだけではなく、中にも(つまりパターンが期待されているところに)書ける

Option(1) match {
  case Some(x @ y) => x + y
  case None => 0
}

// => Int = 2

ところで、@によって2回変数束縛できてお得!!!とは言ったが、実はこれは正確ではない。なぜなら、@の前にはパターンではなく変数しか置けないからである。

Pattern Matching | Scala 2.12の8.1.3、Pattern Bindersを見てほしい。

A pattern binder x@p consists of a pattern variable x and a pattern p. The type of the variable x is the static type T of the pattern p. This pattern matches any value v matched by the pattern p, provided the run-time type of v is also an instance of T, and it binds the variable name to that value.

とある通り、 x @ pxp というパターンによって表される型の変数である。パターンではない。

なので、「2回束縛できてお得!」というのはあまり正確ではなくて、@の前に「@の後ろに書かれたパターン全体にマッチしたものを束縛する変数」がかけて、そのあとに細かいパターンを書ける。結果として、パターン全体にマッチしたものが束縛される変数と、パターンによって細かく束縛された変数がどちらも得られるという感じである。実際、以下のようなパターンはコンパイルエラーとなる。Some(x)はパターンであって変数ではないからである。

Option(1) match {
  case Some(x) @ Some(y) => x + y
  case None => 0
}

というわけで、冒頭の「List(1, 2) match { case Seq(xs @ _*) => println(xs) }」については、まず List(1, 2)の中身に、@の後ろのパターン_* がマッチし、マッチした全体をxsに束縛する、という挙動をすることになる。List(1, 2) match { case Seq(_*) => println("hoge") } では、Listの中身が取り出せないが、List(1, 2) match { case Seq(xs @ _*) => println(xs) }ならば中身をxsという変数に束縛できる、というわけだ。

FluxのStoreがViewModelかって話からのMVWとかどうでもいいって話

StoreがViewModel相当かどうかってことそれ自体はたぶんあんま本質じゃないんだけど。

blog.nkzn.info

これについてです。

念のため言っておくけど、「どうでもいい」ってのは「知らなくていい」って意味じゃなくて、「知った上で捨てれるのが大事」みたいな話ですね。そもそもiOSでもAndroidでもAngularでもVueでもそもそもフレームワークがMVWの概念に乗っかって作られてるんだから知らなくていいはずないという話はありますね

労働と要らんもんと豊かさ

マネジメントの放棄を正当化するような格言めいたものがこの世には流通しているかもしれない

ちょっと前にツイッターで以下のようなことを書いた。

「自分で考えて動く」みたいなのすごい大事だとぼくも思うけれど、それをするためには「どんな役割を担ってほしいか」「達成してほしいことはなにか」「どこまで自分の裁量でやっていいか」がそれぞれ明確になってないと無理だよね。逆にそこさえ揃ってれば、よほどのタコじゃない限り自分で動くと思う

これに対して、「マネージャーがそれをやらないのはマネジメントの放棄だよね」というリプライがついて、「なるほどたしかにそうだなあ」と思ったのだけれど、マネジメントの放棄と呼ぶべき状況ってのは、これの他にも、ちょっと注意して見てみるといろいろなところで目にすることがあるかもしれない。

たとえば、たまに耳にする「社会人は結果が全て」という言葉について。ここでいう「結果」というのはなんだろう。マネジメントするひととされる人の間で「あなたが達成すべき結果はこれですよ、これに向けて頑張ってください」がきちんと合意と納得の上で設定されているのであれば、いいと思う。けど、この言葉が使われる文脈は、なんだか多くの場合「いいから売上あげろや(売上を上げるためのプロセス目標などは特に設定されない)」みたいな感じの上にあるような気がする(要出典)。

もう少し別の言い方をすると、たとえば、まだひとりで案件を受注まで持っていけないひとや、プログラマであれば、ひとりでプロダクトを完成まで持っていけるスキルがないひとに対して、「結果が全てです、あなたは案件を受注してないので結果なしです」「結果が全てです。あなたはプロダクトを完成させられなかったので結果なしです」と言ってしまうのは、マネジメントの放棄と言って差し支えないだろう。

そういう人達には、たとえば、「まずは一ヶ月にn社とアポを取って面談することを目標にしましょう」だとか、「メンターとコミュニケーションを密に取って、一日ふたつプルリクがマージされるのを目標にしましょう」だとか、そういう「会社にとってプラスになる行動だし、本人にちゃんと達成できる目標」をきちんと(相談の上)設定する必要があるだろう、というような話だ。

多分、冒頭に書いた例や今書いた例に限らず、いろんなところでマネジメントの放棄や、それがあたかも格言めいた言い方で正当化されることが起こっている気がする。なんとなくそう思うってだけで確証があるわけではないのだけれど。

ひとりひとりのメンバーに対して適切なマネジメントレベルも違う(この記事でぼくがあげたようなレベルのマネジメントが不要なハイレベル人材もいますよね)から、マネージャーってけっこう大変な仕事だと思う。だから、ついつい自分の耳に甘く響く「マネジメント放棄を正当化する格言」に逃げちゃったりしがちかもしれないけど、だからこそそういう言葉にうっかり乗っかってしまわないように気をつける必要があるよな、と感じた。

蛇足を書いておくと、もちろん、マネジメントされる側が自分を律するためにそういうの使うってのはあってもいいかもしれないけど、マネジメント放棄されてるところで無理に頑張ると心が壊れるので、そういう時は無理しないでほしい。

JavaScriptのreduceがゆるゆる型であることに助けられた話

某slackにて以下のようなお題が出されました。

お題

["a","b","c","d"] みたいな配列があった時に

{
  "a": {
    "b": {
      "c": "d"
    }
  }
}

みたく変換する良い方法を JavaScript で募集します

わたしの回答

const reducer = (acc, el) => {
  const ret = {};
  ret[el] = acc;
  return ret;
};

["a", "b", "c", "d"].reverse().reduce(reducer);

与太話

普通(普通ってなんだ?)、reduceは配列の要素をひとつひとつ舐めて、変換をしながらaccumulatorに蓄積していくような操作になりますが、静的型付け言語の場合は以下のようなシグネチャになることが多いでしょう。(架空の言語です)

class Array[A] {
  def reduce[B](reducer: (acc: B, element: A) => B, initialAcc: B): B = ???
}

畳み込みはつまり Array of AB に変換する仕組みですから、reducerの型が「(acc: B, element: A)をとり、Bを返す関数」になるのは自然なことです。さらに、accumlatorの初期状態を必要とするので、reducereducerの他に「accumlatorの初期状態」を引数にとります。

しかし、JavaScriptreduceはこの「accumlatorの初期状態」を省略することができます。

[1, 2, 3].reduce((acc, el) => acc + el); => 6

省略した場合、一回目のreducerの引数にはArrayの1要素目と2要素目が渡ってくるという親切(!)な仕様です。

しかし、この挙動は、Arrayの要素の型とaccumlatorの型(=reduceの返り値の型)が同一の場合はうまくいきますが、異なる場合は奇妙な挙動をすることになります。

たとえば、Arrayの要素の型がnumberで、accumlatorの型がobjectの場合を考えてみましょう。

一回目のreducerの引数には、numbernumberが渡ってくることになりますが、二回目以降のreducerには、objectnumberが渡ってくることになります。

これはかなり奇妙な挙動で、普段ならばバグの温床になりそうなものです。

が、今回に限ってはこの挙動に助けられました。

お題で得たいオブジェクト

{
  "a": {
    "b": {
      "c": "d"
    }
  }
}

の形をよくみてください。厄介そうなやつがいますね。そうです、一番深いネストの、"c": "d"の部分です。これが、

{
  "a": {
    "b": {
      "c": {
        "d": {}
      }
    }
  }
}

という形であれば、配列のすべての要素をキーに変換していけばいいだけなので話は簡単なのですが、お題では、ネストの一番深い部分だけが「キーが文字列、値も文字列」で、ほかの部分は「キーは文字列、値はオブジェクト」です。これは困りましたね。普通のreduceでは対応するのはかなり難しそうです…… 。

しかし、JavaScriptreduceは「ちょっと普通じゃない」のです!「accumlatorの初期状態を省略すると最初の一回だけは配列の1番め、2番目の要素を渡してくる」という仕様があるのでした!こいつを悪用してやれば、「一番奥のネストは文字列と文字列のペア」「その他の部分は文字列とオブジェクトのペア」というのをうまく表現できそうです!

という発想で、前掲した解にたどりついたのでした。

JavaScriptの挙動を悪用したハックっぽい感じで、静的型付きの世界からするとかなりお行儀の悪い書き方に感じますが、たまにこういうゆるい型がうまくはまるというか悪用できるケースにあたるとガリガリくんの「当たり」をみつけたような気持ちになりますね。

こちらからは以上です。