未来の重圧/case classをやめた

未来のある時点に向かって準備しなくてはいけないものが出現したのでなんとなく落ち着かない気分だ。大学にいる頃からこの感覚がひどく苦手で、会社員になるとだいぶ緩和されていたのだが、やはり人生そう甘くはない。毎日死の準備をしながら生きていこうな。

Scalaのクラスはcase classにするとapplyメソッドが自動で生えるのだが、これと合わせてコンパニオンオブジェクトで自前のapplyも実装するとコンパイラがどっちを使うか判断できなくて怒る。

sealed abstract case classという手もあるらしいが、インスタンス化したいクラスなのでこの手は使えない。結局どうにも出来なかったのでcase classにすることをやめた。それほど恩恵を受けていたわけでもないし。

久々に酒を飲んだ/酒を飲んでプログラミングをするな

※この記事は『ほろよい もも』を飲んで書かれた。

月の始めに強い意志で(ほぼ)定時退社。制度上定時はないが自分で11時から20時を勤務時間と決めている。

いろいろな事情でSlackのワークスペースが増えてきたのでLinux用のアプリケーションをインストールしたのだが、ワークスペースにログインできずにいる。ブラウザでログインした後アプリケーションに処理が移らない。

仕事でTypeScriptをやってはいるが、趣味開発で初めて裸のtscコマンドによるコンパイルをやった。コンパイルのバージョンがどうなっているのかよくわからない。前者も後者もコンパイルは通るのに前者しか動かなかったりする。

import * as Hoge from "hoge";
import Hoge from "hoge";

完全に酒に酔って意味不明ムーブ繰り出してる。間違ってaccess tokenをpushしてしまったので定石どおりリポジトリ削除→再作成→pushをやったのだが、修正をaddしないままcommit --amendしていたので無意味だった。やり直し。

ScalaでUnion型

普段仕事ではTypeScriptを書いているので
const x: "kinoko" | "takenoko" = "kinoko";
みたいなの(Union型という)に見慣れていた。

趣味ではScalaを書いており、同じようなものを書きたくなった。具体的にはActiviryPubのActor Typesを表現するためにApplication, Group, Organization, Person, Serviceのどれかの値(いずれも文字列)をとるという型を作りたかった。

case class

しかし調べてみるとScalaにUnion型はない。自分でパッと思いついたのはcase classだ。ドワンゴのScalaテキストに近い用例が載っている。下にそれを引用する。

sealed abstract class DayOfWeek
case object Sunday extends DayOfWeek
case object Monday extends DayOfWeek
case object Tuesday extends DayOfWeek
case object Wednesday extends DayOfWeek
case object Thursday extends DayOfWeek
case object Friday extends DayOfWeek
case object Saturday extends DayOfWeek

sealed修飾子をスーパークラス/トレイトに付けることによって、その(直接の)サブクラス/トレイトは同じファイル内にしか定義できない

ので、パターンマッチするときにコンパイラがいい感じにチェックしてくれるというメリットがある。

上記を参考にこんな感じで実装してみた。欲しいのは文字列なので、toStringをoverrideしてクラス名をそのまま取得できるようにした。

objectにするとgetClass.getNameの末尾に$がついてしまうのでinitしている。最後の1文字を除去するというメソッドがある多機能さ、いかにもScalaっぽい。あるいはcase objectじゃなくてcase classにすればこんな小細工は不要だが、パラメータリストが必要になるという面倒臭さがある。どうあるべきなのか、自信ニキは教えてほしい。

Enum

もう一つ、これは同僚に教えてもらったものだが、Enum型を使う方法もある。

こちらは採用しなかったのであまり深入りしていない。もしかしたらこっちのほうが良かったかもしれない。いや、いま猛烈にそんな気がしている(表現したいのが単なる文字列なので)。

それにしても大事なのはググり力だ。僕が「Scala ユニオン型」で検索してもいい情報は得られなかったが、「代数的データ型」という言葉を知っていればこの記事に辿り着けただろう。思うに、体系的な勉強は裏切らないのだ。

型の道は深く険しい…

爆速帰宅無為ゲーム/ScalaのEvolutionsを捨てた

8/29

月末なので労働時間調整のために早く退勤した。時間が出来たのでDota2を3ゲームやったが全部負けた。自分一人の力ではどうしようもないと感じる負け方だったので辛い。

Scala+Play FrameWorkで作っているアプリケーションでDBの初期化のためにEvolutionsを使おうとしていたのだが

Unexpected exception[JdbcSQLSyntaxErrorException: Table "PLAY_EVOLUTIONS" not found;

というエラーがでてどうやっても解決できなかったので諦めた。情報がなさすぎる。

Evolutionsを使わなくても、適当なクラスのコンストラクタでcreate tableすれば済む話だった。ちゃんと公開するときはDBは別で作ればいいし。

Ubuntu18.04の入力メソッド選択をMac風にした

Macは日本語入力と英語入力にそれぞれキーが割り振られており、そのキーを押せばその入力メソッドになることが保証される。一方でUbuntuはデフォルトだと一つのキーを押すことで切り替わる。これだと今どちらの入力メソッドが有効になっているかわからない。

入力メソッドの設定→全体の設定→Show Advanced Options

「入力メソッドをオンに」/「入力メソッドをオフに」にそれぞれ好きなキーを設定する。僕はMac風にスペースキーの左右のキーを当てた。使ってなかったし。

使ってない、使いみちのわからないキー、あるよね。

vscode拡張のMetalsはPlayの追加パッケージに気づかない

vscodeにMetals拡張を入れてScala+PlayFrameworkの開発をしている。

import play.api.db.Databaseがエラー扱いになるが、コンパイルは通るし動く。play.api.dbplayそのものには存在せず、プラグインに追加によってインポート可能になるからだろうか。よくわからん。

ずーっとエラーと格闘してなんとなく回避法を見つけつつ結局よくわからんになるの、実に個人開発みがあって良い。

TI9観戦/ナウいScala開発環境/口内炎の予感

日曜なので意識的に在宅していた。

TI9観戦

Dota2のTI9がアツい。FnaticがVPに勝つ番狂わせが起きるかと思いきや起きなかった。Dota2の試合時間はだいたい30分から40分くらいだ。ヒーローは大まかにスキルで戦うヒーローと通常攻撃で戦うヒーローに分類される。前者の方が早熟だが、金を稼いでアイテムが揃うにつれて後者の方が強くなる(基本的に時間が経てば金は貯まる)。金を横軸・強さを縦軸に取ると当然右上がりのグラフになるが、グラフの形はヒーローごとに様々だ。たとえば特定のアイテムを持つことで格段に強くなるということがある。プロレベルの試合では味方のヒーローに重要アイテムが入り、かつ敵のヒーローがまだ重要アイテムを手に入れていない絶妙なタイミングで戦いを仕掛けに行くということもある。そこで勝てば金が手に入り、また有利になる。

しかしこうして有利を拡大していっても決めきれなければ大器晩成型のヒーローによって逆転されることもある。たとえばMedusaは通常攻撃が4体攻撃になるスキルを持つ。単純に考えて通常攻撃を強化するアイテムのもたらす恩恵は4倍だ。だから強力なアイテムを揃える前に勝ちきらなければならない。

ナウいScala開発環境

以前vscodeでScala開発を試みたときはまともに使える拡張機能がなく補完が効かなかったのだが、今はMetalsを入れるだけでいい。補完があるとプログラミングは楽だ。ミスに気づくのは早ければ早いほどいい。

今はActivityPubの実装に挑戦している。仕様が固まっているものなのでTDDしている。ActivityPubではObjectはTypeという属性を持つことを定めているが、これは予約語なので`type`と表現する必要がありややこしい。ScalaTestの機能と思っていたmatcherが実はPlayの機能だったりして難しい。フレームワーク周りの知識がない。

素人丸出しのアレだが、package hogeはそのファイルの内容をhogeに所属させるために使うことを知った。つまり他のファイルからhoge.fugaという呼び出しができるようになる。ファイルでもオブジェクトでもクラスでもなく「パッケージに所属させる」という操作の感覚が新しかった。

今日はもうひとつ、droneのデプロイもした。droneはCIの一種でgitリポジトリにpushしたときに.drone.ymlを読んで自動でテストやビルドを行う。1回毎にdockerコンテナを作って捨てることでクリーンな環境でテストできるのがdroneの特徴だが、1回毎にsbtの初期化を行うせいで(貧弱なサーバーでは)1時間以上かかってしまい、タイムアウトしてしまった。

口内炎の予感

口内の傷が嫌な感じに痛み出していて口内炎になりそうで嫌だ。口内炎は食事が楽しめないのが辛い。ただ、火曜に右上の親知らずを抜くのでどうせ1週間くらいはろくな食事ができない。

盆三部作Part.3『法事』

3日目は法事だった。と言っても自宅に和尚が来て10分程度読経してもらうだけだ。例年朝一番なのだが、今年は順番を逆順にしたとのことで午後3時だった。

法事が終わったらすぐ鈍行に乗って東京に出発した。あまり座れなくてしんどかったし、DDD本を読んでも何もわからなくて辛かった。概念も具体例も全部難しい。開発の経験が先にあって初めてわかる本なのかもしれない。今は「こういう概念が存在する」ということだけを覚えておいて、また必要になったときに読むことにしよう(撤退)。

明日仕事マジ?

ActivityPubの仕様読んでた

※この記事は『のどごし生』を飲んで書かれた。

なんとなくデカい遊びをしたくてActivityPubの仕様を読んでる。Mastodonを代表とする分散型サービスには自由があるので(ホンマか?)興味がある。自分が生きた証をネットのいろいろなサービスにバラバラに残すよりは、統一的なフォーマットで自分中心に発信したい。なんてね。

明日は土曜日。土曜日は活動的な休日にする。まだ何をするかはあまり決まってない。嘘。映画見てオフィスで使う小物を買ってプレゼントを見繕う。くらいまでできれば上等かな。日曜日は家から出ないぞ。

久々にDota2で勝ち星が偏ってAncient3に昇格した。と言っても1種類のヒーローをスパムしているのでメタヒーローを取られると結構キツい。が、1stピックのサポートをメタられたところでチームとしてはどうということはない。味方の他のヒーローがメタり返せばいいのだ。

チームワークが重要なゲームなので味方と煽り合いが始まるとまず負ける。そういうときはミュートに限る。

歯バトル・ファイナル8/20

いつまでやってんだという話だが、4月から続いている歯とのバトルは8月20日に右上親知らずの抜歯が決まったことによってひとまず決着しそうだ。なんで長引いたかと言うと右上の親知らずを抜くべきか抜かざるべきか、かかりつけ医とデカい病院の口腔外科医の意見が微妙に異なり(対立というほどではない)、そこに僕自身の迷いが重なったからだ。

いよいよ夏が来ている。僕の通勤ルートは徒歩の割合が大きい。早く歩けば歩くほど発汗は増えるだろうが、ゆっくり歩いて日差しに当たる時間が伸びてもやはり発汗は増える。つまりどこかに最適な歩行速度があるはずなのだ。発汗のことはともかく、歩行には最適な速度がある。伸ばした足が直線であると仮定すると(ホンマか?)、その足を半径として体が円弧を描く遠心力と重力が釣り合うのが2.5m/sだという。つまりこれより早く歩行しようとすると無理な体勢を強いられ、エネルギー効率が悪化する。このモデルは大雑把だが実測した歩行→走行の移行ポインともだいたい一致するようだ。詳しくはAlexandar(1984)に書いてあると思う。僕は直接読んでなくて教科書で紹介されてるの読んだだけだけど(学問的に不誠実な発言)。

京都アニメーション放火殺人事件の犠牲者の遺族を自称するツイッターアカウントがにわかに出現し、マスコミの強引な取材を「告発」し20万RTを超えている。「ウソをウソだと見抜ける人でないと難しい」はどこに行ったのか。本当の遺族は遺族じゃない人に比べてああいうツイートをする確率は確かに高いだろうが、そうは言っても遺族じゃない人の方が世界には圧倒的に多い。つまりあのツイートの主が本当の遺族である確率は非常に低いことになる。ベイズの定理というやつだ(詳しくない)(これ読んで)。

2連続で大学の知識の残滓を披露してしまって辛い。じゃあ新しいことを勉強できているかと言うと、まあできてなくもない。DDDを簡単に説明した同人誌をそろそろ読み終わるので本格的な本を読み始めたい。しかし、有名な教科書がKindle Cloud Readerで読めない。辛い。紙の本で買うと値段が倍になる。辛い。