虚無庵

徒然なるままに

個人的に不完全燃焼だから自分のボケを自分で解説する

speakerdeck.com

RubyKaigi 2019 LT で話した内容だが

うん、自分でもそう思う。だから気持ちよく令和を迎えるために自分のボケを自分で解説する。結局平成中には間に合わず。

Proposal 内容

RubyKaigi の proposal は「自分でコード書く。そして晒す。それについて話す」というシンプルな自慢話大会なので、作文力が高くてもあまり評価されない(らしい)。なので備忘録的に proposal を晒す。

Title

How to Make Bad Source

Abstract

If you are a programmer, you aspire to write source code that is easy to read. Obviously, right? However, occasionally we want to write source code that is difficult to read, like tric · GitHub.
This talk is about how to produce source code like TRICK.

Details

I made the hazama_kuroo | RubyGems.org | your community gem host gem that can play Blackjack.
What is interesting isn't the Blackjack game itself, but its source code which looks like this(https://github.com/jinroq/hazama_kuroo/blob/hk_0.2.4/lib/hazama_kuroo.rb). It's ASCII art!
This talk is how to produce source code that also doubles as ASCII art.

Pitch

There are many programmers who want to make applications like TRICK (I am one of them).
If the audience hopes to hear about "How a newbie, non-specialist made source code like TRICK," I am well qualified to deliver this talk as a newbie that actually made such an app whose source is ASCII art.

記憶を辿る

一週間前の自分は赤の他人なので、可能な限り記憶を辿ってみる。といってもソースコードとスライドがあるので大分楽。なお、以下はスライドや proposal とは粒度を変えて可能な限り再現できるように詳細に書いてみる。

Step 0.

そもそもでなんでブラックジャックを選んだかというと

  • 自分のモチベーションを保つためには興味のありそうなもの(簡単に動かせて簡単に動作確認できるもの)が良さそう
  • 数あるゲームの中で基本ルールが一番単純そう
  • hazama_kuroo という gem 名を思いついてしまった

というのが主な理由です。

Step 1.

「シンプルなルールのブラックジャックをごくごく普通に実装する」と keynote のメモに残っていた。ルールは wikipedia を参考にした。ベットのめんどくさいルールは全て省き、「プレイヤーは 21 を目指してひたすらヒット可能」「ディーラーは 17 以上 21 以下の範囲でヒットする」というものにした。

また「source」と「sauce」をかけた「Spaghetti Source」だったが、「source」が調味料とコードの 2 つの意味を持つと盛大に勘違いしていたことをマクドナルドのハッピーセット購入時に気付いた。 spaghetti code を誤って覚えている残念な子みたいになって大変残念である。

Step 2.

スライドでは以下のようなメモを書いていた。

  1. Step 1. で実装した仕様を変更しない
  2. 実装予定のアスキーアートのパターンを複数用意する
  3. eval %w[ ].join('') で実行できるよう Step 1. の実装をワンライナーで書き直す
Step 1. で実装した仕様を変更しない

LT では最初に話したものの、実は最初から変更しないと決めていたわけではない。ただ、実装していくにあたり「仕様がとっちらかるとゴールが見えないな」と感じたので制約として設けてみた。LT を実際に聞いた方はご存知かと思うが、実装進めていくにあたり結構軽いノリで機能追加はした。

実装予定のアスキーアートのパターンを複数用意する

これも最初から用意していた訳ではなく、実装を進めていくうえで「ピンポイントの文字数で実装するの無理ゲー」と気付いたので、文字数の異なる AA パターンを用意した。また、

f:id:jinroq:20190508195842p:plain
AA のパターン

「この 2 パターンのうち下のパターンを選んだ」と話したが、上のパターンでいい感じに収まる気がしなかったので問答無用で下のパターンにした。

eval %w[ ].join('') で実行できるよう Step 1. の実装をワンライナーで書き直す

実はどうやれば AA のコードが書けるか全く下調べもせずに Step 1. をやってしまったが為に、えらい苦労する羽目になった。LT でも話したがかなり M っ気の強い作業のオンパレードだった。

Step 2. と Step 3. の間

mrkn さんのツイートを見て「そういえば!」となった。Step 3. ではプロトタイプを作っているが、その前にやったことがあった。

  • AA を 0/1 で書き換える

いわゆる

f:id:jinroq:20190508202433p:plain
こんなやつ

こんなやつです。これをやってからプロトタイプ作成に取り掛かった。

Step 3.

メモでは「プロトタイプ作成」とか書いてた。で、プロトタイプを作成するために、先ほど 0/1 に変換した AA の「0 をスペース」「1 をコード」に変換していった。うまい感じの変換ツールができなくて、最初はハンドメイドで書き直した。超マゾイ。

その結果、出来上がった AA は typo しているは変なバグあるわとダメダメだった。

Step 4.

バグを直しつつ、ワンライナーのコードをもっと圧縮できないかロジックを組み直したりした。不思議なことに何度もこんな変なコードを書いていると AA 化したままでもソースが読めるという特殊能力を習得したりした。使い所がない。

で、圧縮しすぎて文字数が足りなくなり、絶対通ることがない if false end なコードを書いたりしたわけである。コメントだとあまりにもあれなんでそれっぽいコードにしてみた。

Step 5.

そして最終形態。機能追加をして微調整した。

Step. Extra

実はもうちょっと機能拡張をする予定だった。だって他の登壇者が強そうに思えたんだもん…。色々やってみたけど、タイムオーバーで即席に id:nagachika さんのセリフや id:tagomoris さんのセリフをパクった使わせてもらった。

まとめ

やってみると案外楽しいです。来年は hazama_kuroo を拡張しても LT 通りそうにないんで、別ネタ考えます。