今日、私が学んだこと

2024-05-30 23:59:59 +0900

ここ1年ほど Ruby のパーサーがもりあがっているので、 lrama の作者を講師にした 通称ドラゴンブックの「コンパイラ」読書会 に参加しています。

4.8.1 節の「競合解消のための優先順位と結合性」を読み感想を言い合う場で、 以下のような話になった。(細かいとろこは本を読んでくれ

  • id + id * id
    • + は * より優先度が低いため shift
  • id * id + id
    • * は * より優先度が高いため reduce
  • id + id + id
    • + は左結合なので reduce
  • id = id = id
    • = は右結合なので shift

ここでそういえば Ruby ではどう動くのだろうかとおもい、次の式をirbで書いてみた 0 - i = 1 + j = 2 * 3 #=> -7 とまあ普通(?)の答えが返ってきた。 でも上のパーサーの条件考えてみるとそもそもこのコードはほかのプログラミング言語で パースできるのだろうかと思い、やってみた。

$ python -c '0 - j = 1 + j = 2 * 3'
  File "<string>", line 1
    0 - j = 1 + j = 2 * 3
    ^^^^^
SyntaxError: cannot assign to expression
$ perl -e '0 - j = 1 + j = 2 * 3'
Can't modify addition (+) in scalar assignment at -e line 1, at EOF
Execution of -e aborted due to compilation errors.
$ lua -e '0 - j = 1 + j = 2 * 3'
lua: (command line):1: unexpected symbol near '0'
$ crystal eval '0 - j = 1 + j = 2 * 3'
syntax error in eval:1
Error: unexpected token: "="
$ ruby -e '0 - j = 1 + j = 2 * 3'

$

:thinkingface:???とにかく Ruby は通るが他のプログラミング言語で通らないことがわかった。

さいごに Ruby の AST がどうなってるのかとりあずみてみた。

$ ruby -e 'pp RubyVM::AbstractSyntaxTree.parse "0 - j = 1 + j = 2 * 3"'
(SCOPE@1:0-1:21
 tbl: [:j]
 args: nil
 body:
   (OPCALL@1:0-1:21 (LIT@1:0-1:1 0) :-
      (LIST@1:4-1:21
         (LASGN@1:4-1:21 :j
            (OPCALL@1:8-1:21 (LIT@1:8-1:9 1) :+
               (LIST@1:12-1:21
                  (LASGN@1:12-1:21 :j (OPCALL@1:16-1:21 (LIT@1:16-1:17 2) :* (LIST@1:20-1:21 (LIT@1:20-1:21 3) nil)))
                  nil))) nil)))

まあわかるような木構造になってますね。 それはそうとパーサーどうなってるんですかねえという話でおわり。

Ruby を KOMPO してみた

2024-05-29 23:59:59 +0900

RubyKaigi2024 の発表、It’s about time to pack Ruby and Ruby scripts in one binary で話されていた kompo を試してみた。

じゅんびというかとらしゅーというかうごかすまでのきろく

とりあえず動かしてみましょう!!

$ gem install kompo
$ mkdir hello; cd hello;
$ echo puts \"hello, world\" > hello.rb
$ kompo
which: no brew in (/home/katsyoshi/.rbenv/versions/3.3.1/bin:/home/katsyoshi/.rbenv/libexec:/home/katsyoshi/.rbenv/plugins/ruby-build/bin:/home/katsyoshi/.local/share/zinit/plugins/rust/bin:/home/katsyoshi/.local/share/zinit/plugins/sk/bin:/home/katsyoshi/.local/share/zinit/plugins/hs/bin:/home/katsyoshi/.local/share/zinit/plugins/fd/bin:/home/katsyoshi/.rbenv/shims:/home/katsyoshi/.rbenv/bin:/home/katsyoshi/.pyenv/plugins/pyenv-virtualenv/shims:/home/katsyoshi/.pyenv/shims:/home/katsyoshi/.pyenv/bin:/home/katsyoshi/.local/share/zinit/polaris/bin:bin:/home/katsyoshi/.go/bin:/home/katsyoshi/bin:/home/katsyoshi/.bin:/usr/lib/llvm/17/bin:/usr/lib/llvm/18/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin)
which: no brew in (/home/katsyoshi/.rbenv/versions/3.3.1/bin:/home/katsyoshi/.rbenv/libexec:/home/katsyoshi/.rbenv/plugins/ruby-build/bin:/home/katsyoshi/.local/share/zinit/plugins/rust/bin:/home/katsyoshi/.local/share/zinit/plugins/sk/bin:/home/katsyoshi/.local/share/zinit/plugins/hs/bin:/home/katsyoshi/.local/share/zinit/plugins/fd/bin:/home/katsyoshi/.rbenv/shims:/home/katsyoshi/.rbenv/bin:/home/katsyoshi/.pyenv/plugins/pyenv-virtualenv/shims:/home/katsyoshi/.pyenv/shims:/home/katsyoshi/.pyenv/bin:/home/katsyoshi/.local/share/zinit/polaris/bin:bin:/home/katsyoshi/.go/bin:/home/katsyoshi/bin:/home/katsyoshi/.bin:/usr/lib/llvm/17/bin:/usr/lib/llvm/18/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin)
/home/katsyoshi/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0/gems/kompo-0.2.0/lib/kompo.rb:110:in `valid?': kompo-cli not found. Please install 'kompo-cli'. (RuntimeError)
        from /home/katsyoshi/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0/gems/kompo-0.2.0/lib/kompo.rb:120:in `block in cd_work_dir'
        from /home/katsyoshi/.rbenv/versions/3.3.1/lib/ruby/3.3.0/tmpdir.rb:99:in `mktmpdir'
        from /home/katsyoshi/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0/gems/kompo-0.2.0/lib/kompo.rb:118:in `cd_work_dir'
        from /home/katsyoshi/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0/gems/kompo-0.2.0/exe/kompo:8:in `<top (required)>'
        from /home/katsyoshi/.rbenv/versions/3.3.1/bin/kompo:25:in `load'
        from /home/katsyoshi/.rbenv/versions/3.3.1/bin/kompo:25:in `<main>'

「なるほどなるほど、 brew が必要なのか。そっかー。」 とおもったのだが、そもそも今 Linux だぞ?となり、リポジトリを見ることに。 リポジトリを見ると kompo-vfs をインストールしろと書いてあるな。 Building に書いてあるように、ダンロードして手元でビルドして、環境変数を設定してみる。

$ git clone git@github.com:ahogappa0613/kompo-vfs
$ cd kompo-vfs && cargo build --release
$ export KOMPO_CLI=$(realpath target/release/kompo-cli)
$ export LIB_KOMPO_DIR=$(realpath target/release)
$ kompo
which: no brew in (/home/katsyoshi/.rbenv/versions/3.3.1/bin:/home/katsyoshi/.rbenv/libexec:/home/katsyoshi/.rbenv/plugins/ruby-build/bin:/home/katsyoshi/.local/share/zinit/plugins/rust/bin:/home/katsyoshi/.local/share/zinit/plugins/sk/bin:/home/katsyoshi/.local/share/zinit/plugins/hs/bin:/home/katsyoshi/.local/share/zinit/plugins/fd/bin:/home/katsyoshi/.rbenv/shims:/home/katsyoshi/.rbenv/bin:/home/katsyoshi/.pyenv/plugins/pyenv-virtualenv/shims:/home/katsyoshi/.pyenv/shims:/home/katsyoshi/.pyenv/bin:/home/katsyoshi/.local/share/zinit/polaris/bin:bin:/home/katsyoshi/.go/bin:/home/katsyoshi/bin:/home/katsyoshi/.bin:/usr/lib/llvm/17/bin:/usr/lib/llvm/18/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin)
which: no brew in (/home/katsyoshi/.rbenv/versions/3.3.1/bin:/home/katsyoshi/.rbenv/libexec:/home/katsyoshi/.rbenv/plugins/ruby-build/bin:/home/katsyoshi/.local/share/zinit/plugins/rust/bin:/home/katsyoshi/.local/share/zinit/plugins/sk/bin:/home/katsyoshi/.local/share/zinit/plugins/hs/bin:/home/katsyoshi/.local/share/zinit/plugins/fd/bin:/home/katsyoshi/.rbenv/shims:/home/katsyoshi/.rbenv/bin:/home/katsyoshi/.pyenv/plugins/pyenv-virtualenv/shims:/home/katsyoshi/.pyenv/shims:/home/katsyoshi/.pyenv/bin:/home/katsyoshi/.local/share/zinit/polaris/bin:bin:/home/katsyoshi/.go/bin:/home/katsyoshi/bin:/home/katsyoshi/.bin:/usr/lib/llvm/17/bin:/usr/lib/llvm/18/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin)
/home/katsyoshi/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0/gems/kompo-0.2.0/lib/kompo.rb:112:in `valid?': Entrypoint not found: '/home/katsyoshi/hello/main.rb'. Please specify the entry file path with '-e' or '--entrypoint' option. (RuntimeError)
        from /home/katsyoshi/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0/gems/kompo-0.2.0/lib/kompo.rb:120:in `block in cd_work_dir'
        from /home/katsyoshi/.rbenv/versions/3.3.1/lib/ruby/3.3.0/tmpdir.rb:99:in `mktmpdir'
        from /home/katsyoshi/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0/gems/kompo-0.2.0/lib/kompo.rb:118:in `cd_work_dir'
        from /home/katsyoshi/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0/gems/kompo-0.2.0/exe/kompo:8:in `<top (required)>'
        from /home/katsyoshi/.rbenv/versions/3.3.1/bin/kompo:25:in `load'
        from /home/katsyoshi/.rbenv/versions/3.3.1/bin/kompo:25:in `<main>'

まだ駄目みたですね。エラーメッセージを見ると -e でエントリーポイントを指定しろとあるな。 ということで kompo -e hello.rb と入力してみますね。

$ kompo -e hello.rb
...snip...
gcc -O3 -Wall -I/tmp/d20240530-1369030-t2mico/dest_dir/include/ruby-3.3.0/x86_64-linux -I/tmp/d20240530-1369030-t2mico/dest_dir/include/ruby-3.3.0 -L/tmp/d20240530-1369030-t2mico/dest_dir/lib -L/home/katsyoshi/Program/Ruby/kompo/kompo-vfs/target/release  main.c -Wl,--start-group  fs.o /tmp/d20240530-1369030-t2mico/ruby/ext/extinit.o /tmp/d20240530-1369030-t2mico/ruby/enc/encinit.o /tmp/d20240530-1369030-t2mico/ruby/ext/bigdecimal/bigdecimal.a /tmp/d20240530-1369030-t2mico/ruby/ext/cgi/escape/escape.a /tmp/d20240530-1369030-t2mico/ruby/ext/continuation/continuation.a /tmp/d20240530-1369030-t2mico/ruby/ext/coverage/coverage.a /tmp/d20240530-1369030-t2mico/ruby/ext/date/date_core.a /tmp/d20240530-1369030-t2mico/ruby/ext/digest/bubblebabble/bubblebabble.a /tmp/d20240530-1369030-t2mico/ruby/ext/digest/digest.a /tmp/d20240530-1369030-t2mico/ruby/ext/digest/md5/md5.a /tmp/d20240530-1369030-t2mico/ruby/ext/digest/rmd160/rmd160.a /tmp/d20240530-1369030-t2mico/ruby/ext/digest/sha1/sha1.a /tmp/d20240530-1369030-t2mico/ruby/ext/digest/sha2/sha2.a /tmp/d20240530-1369030-t2mico/ruby/ext/erb/escape/escape.a /tmp/d20240530-1369030-t2mico/ruby/ext/etc/etc.a /tmp/d20240530-1369030-t2mico/ruby/ext/fcntl/fcntl.a /tmp/d20240530-1369030-t2mico/ruby/ext/fiddle/fiddle.a /tmp/d20240530-1369030-t2mico/ruby/ext/io/console/console.a /tmp/d20240530-1369030-t2mico/ruby/ext/io/nonblock/nonblock.a /tmp/d20240530-1369030-t2mico/ruby/ext/io/wait/wait.a /tmp/d20240530-1369030-t2mico/ruby/ext/json/generator/generator.a /tmp/d20240530-1369030-t2mico/ruby/ext/json/parser/parser.a /tmp/d20240530-1369030-t2mico/ruby/ext/monitor/monitor.a /tmp/d20240530-1369030-t2mico/ruby/ext/nkf/nkf.a /tmp/d20240530-1369030-t2mico/ruby/ext/objspace/objspace.a /tmp/d20240530-1369030-t2mico/ruby/ext/openssl/openssl.a /tmp/d20240530-1369030-t2mico/ruby/ext/pathname/pathname.a /tmp/d20240530-1369030-t2mico/ruby/ext/psych/psych.a /tmp/d20240530-1369030-t2mico/ruby/ext/pty/pty.a /tmp/d20240530-1369030-t2mico/ruby/ext/rbconfig/sizeof/sizeof.a /tmp/d20240530-1369030-t2mico/ruby/ext/ripper/ripper.a /tmp/d20240530-1369030-t2mico/ruby/ext/socket/socket.a /tmp/d20240530-1369030-t2mico/ruby/ext/stringio/stringio.a /tmp/d20240530-1369030-t2mico/ruby/ext/strscan/strscan.a /tmp/d20240530-1369030-t2mico/ruby/ext/syslog/syslog.a /tmp/d20240530-1369030-t2mico/ruby/ext/zlib/zlib.a /tmp/d20240530-1369030-t2mico/ruby/enc/libenc.a /tmp/d20240530-1369030-t2mico/ruby/enc/libtrans.a -lkompo -lruby-static -Wl,-Bstatic -lz -lrt -lgmp -lcrypt -lffi -lssl -lcrypto -lyaml -Wl,-Bdynamic -ldl -lm -lpthread -Wl,--end-group -o hello
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: -lgmp が見つかりません: そのようなファイルやディレクトリはありません
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: -lffi が見つかりません: そのようなファイルやディレクトリはありません
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: -lssl が見つかりません: そのようなファイルやディレクトリはありません
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: -lcrypto が見つかりません: そのようなファイルやディレクトリはありません
/usr/lib/gcc/x86_64-pc-linux-gnu/13/../../../../x86_64-pc-linux-gnu/bin/ld: -lyaml が見つかりません: そのようなファイルやディレクトリはありません
collect2: エラー: ld はステータス 1 で終了しました
...snip...

いったとおもったら、今度はライブラリ(libgmp、libffi、openssl、libcrypt、libyaml)のリンクができないようですね。 必要なライブラリはインストールされているのか見てみましょう。

$ eix -ICU 'dev-libs' -s 'gmp|libcrybp|libffi|libyaml|openssl'
[I] dev-libs/gmp
     Available versions:  6.3.0-r1(0/10.4)^d {+asm +cpudetection +cxx doc pic static-libs ABI_MIPS="n32 n64 o32" ABI_S390="32 64" ABI_X86="32 64 x32"}
     Installed versions:  6.3.0-r1(0/10.4)(02時44分45秒 2024年05月30日)(asm cpudetection cxx -doc -pic -static-libs ABI_MIPS="-n32 -n64 -o32" ABI_S390="-32 -64" ABI_X86="64 -32 -x32")
     Homepage:            https://gmplib.org/
     Description:         Library for arbitrary-precision arithmetic on different type of numbers

[I] dev-libs/libffi
     Available versions:  3.4.4-r4(0/8)^t ~3.4.6(0/8)^t {debug exec-static-trampoline pax-kernel static-libs test ABI_MIPS="n32 n64 o32" ABI_S390="32 64" ABI_X86="32 64 x32"}
     Installed versions:  3.4.4-r4(0/8)^t(02時43分18秒 2024年05月30日)(-debug -exec-static-trampoline -pax-kernel -static-libs -test ABI_MIPS="-n32 -n64 -o32" ABI_S390="-32 -64" ABI_X86="64 -32 -x32")
     Homepage:            https://sourceware.org/libffi/
     Description:         Portable, high level programming interface to various calling conventions

[I] dev-libs/libyaml
     Available versions:  0.2.2^t 0.2.5^t {doc static-libs test}
     Installed versions:  0.2.5^t(02時44分57秒 2024年05月30日)(-doc -static-libs -test)
     Homepage:            https://github.com/yaml/libyaml
     Description:         YAML 1.1 parser and emitter written in C

[I] dev-libs/openssl
     Available versions:  [M]1.0.2u-r1^td [M]1.1.1w(0/1.1)^t 3.0.11(0/3)^t 3.0.12(0/3)^t 3.0.13(0/3)^t ~3.0.13-r1(0/3)^t 3.0.13-r2(0/3)^t ~3.1.5-r1(0/3)^t ~3.1.5-r2(0/3)^t ~3.2.1-r1(0/3)^t ~3.2.1-r2(0/3)^t **3.3.0(0/3)^t {+asm bindist fips gmp kerberos ktls rfc3779 sctp sslv2 (+)sslv3 static-libs test tls-compression (+)tls-heartbeat vanilla verify-sig weak-ssl-ciphers ABI_MIPS="n32 n64 o32" ABI_S390="32 64" ABI_X86="32 64 x32" CPU_FLAGS_X86="sse2"}
     Installed versions:  3.0.13-r2(0/3)^t(02時43分56秒 2024年05月30日)(asm -fips -ktls -rfc3779 -sctp -static-libs -test -tls-compression -vanilla -verify-sig -weak-ssl-ciphers ABI_MIPS="-n32 -n64 -o32" ABI_S390="-32 -64" ABI_X86="64 -32 -x32" CPU_FLAGS_X86="sse2")
     Homepage:            https://www.openssl.org/
     Description:         Robust, full-featured Open Source Toolkit for the Transport Layer Security (TLS)

入ってますねこれ…もういちどよくコンパイルしてエラーとなった行をよくみてみましょう。 どのファイルも .a でおわってますね。 ということはこれらのファイルに静的コンパイルされたファイルがなさそうですね。 Gentoo Linux のパッケージマネージャー portage では static-libs というオプションをつけてあげることにより静的コンパイルされます。

$ doas emerge -uDN world
$ kompo -e hello.rb
...snip...
$ ./hello
`RubyGems' were not loaded.
`error_highlight' was not loaded.
`did_you_mean' was not loaded.
`syntax_suggest' was not loaded.
hello, world

yatta!!ugoita!!!

まとめ

kompo を動かしてみました。 コンパイルに時間がかかりますが、これで Ruby のプログラムを簡単に配ることができそうですね。

最果ての沖縄に行ってきた

2024-05-18 23:59:59 +0900

RubyKaigi2024 の翌日 2024-05-18 から五日間 2024-05-22 まで 沖縄県国頭郡国頭村辺戸に滞在したはなし。

1 日目

RubyKaigi が終ったので東京から来る友人と合流するために那覇空港へ。 友人たちと合流し昼食を食べたので、レンタカーを借りていざ宿へ出発。 この時点で16:00ごろ。空港から宿のある辺戸まで 100 km を越える。 しかも宿周辺には共同売店とよばれる簡易スーパーしかない。 ということは事前に分っていたので、名護周辺で当面の食料調達することに。 まず、高速道路を利用して名護へ。 名護ではオリオンビール工場入口という看板をみつけたのでそこに寄ってみることにした。 そこは酒屋だった。とくになにもなく、オリオンビール500ml*6を買ってでた。 スーパーを見つけたので大量に食品を購入。この日は酒を飲んで話して就寝。

2 日目

この日は、朝7時ごろに集落向けの放送があり目をさましたが、二度寝。 10時ごろみんな起きて宿の近くのヤンバルクイナ展望台へ。 ここまでの移動が意外と起伏が激しく、披露困憊。ここからの眺めはたいへんよかった。 ここから海岸線まで降りれそうだったが、上で書いたように疲れていたので一旦宿にもどることに。 宿への帰り道。勾配がキツい。午後は昼飯と観光を兼ねて、辺戸岬までいくことに。 辺戸岬は観光地らしく、他の Rubyist たちもどうやら来てたみたい。 ここで岬の先のほうにいったりして見たあと、昼食。 昼食後、夕飯の調達のために名護のスーパーへGO。 昼食中に温泉というかでかい風呂が山の中あったのでそこへ行くを計画。 スーパーで買ったものを宿において、ちょっとだけ休憩してその山の中の風呂へ。 山の中の風呂へ行く途中いい海岸にかんじの砂浜(楚洲の浜)あったのでみんなで砂浜へ。

砂浜を楽しんだので、目的のお風呂、命薬の湯があるやんばる学びの森へ。 道中、道の左右が草で埋まっていてこの先本当にあるのか?という気分になった。 到着。風呂入っているあいだに以下のメッセージが。

そんなわけで18:40ごろ合流。やんちゃさんが電池がないらしかっため少々談笑しながら充電。 やんちゃさんはこのあと名護で用事があったらしいのでここでお別れ。

3 日目

この日は朝からといっても9時ごろから一人で釣りへ。 釣り場へ行くには海岸線を通るのですが、足元を靴ではなくビーサンで行ったためこの道は正規なのかとおもってた。 釣り場着いて先に釣りしているひとに聞いたら、どうやら正規ルートだったらしく、ひとまず安心。 車は一台しかないため昼ごろ宿へもどる。もどったら、仕事中の人がいてそういえば今日は平日だったということを思い出す。 昼は宿で冷凍食品をレンチン。レンジを動かしてたら、なんと無線LANが繋らなくってしまった。 ワーケーションしている友人はオンライン会議中だったが、繋らないと訴えてたためレンジを停止。 東京の自宅居る間で気にしたこと、気になったことなかったけどよくかんがえてみたら レンジ使ってるときにはインターネットしないことが多いのから気にならなかっただけかも。

この日東京へ戻る人が居たので那覇空港へ送りにドライブ。 19:30 ごろ見届けたので帰りにどこか寄って食べたりしようとなった。 が、そもそも宿に帰るのに2時間かかるのでそういうのはやめようと訴えた。 帰る途中で肉の自販機で山羊刺しを購入。 そろそろガソリンが切れそうだったので給油することに。 給油する際に A&W が併設されてたので給油&&軽食。 宿に帰りついて、先程購入した山羊刺しを食べて就寝。

4 日目

この日も午後に東京へ帰るひとがいたので那覇へドライブ。 この日から沖縄は梅雨入り。 送る途中で雨が振りはじめた。 このときまだ梅雨入りしていることはしらなかったのでまあ夕立だろとおもっていた。 昼前だったので、沖縄のソウルフード JEF に行きゴーヤーバーガーを喫食。 空港着いて友人を見送りしたら再び雨が強くなったので沖縄の友人に twitter で聞いてみた。

ということでした。 空港へ送ったあと、午後暇なのでとりあえずひめゆりの塔へ。 駐車場へもどるとき、押しボタン式の信号機だったのに気付かなかった。 そうしてたら、目の前の売店の店員さんが飛び出てきて強い客引きが。 これを躱して車へもどり本島一周の旅へ。 途中車で行ける島、奥武島、宮城島と 浜比嘉島へドライブ。 雨が大変強く、川から流れ込む水で海が二色に。 そのまま沖縄本島の東側を走って宿へもどる。 宿もどってからはオンラインで飲み会後就寝。

LAST DAY

最終日この日に東京へもどるのだが、この日も雨が強く、どしゃ降りだったので宿を早めにチェックアウト。 途中 KING TACOS があったので寄ることに。 この店はタコライス発祥の店らしく、いきたかったのです。 見た目どおり大きく、これは失敗したなと感じましたね。チーズの味が強く大変好みの味でした。 本店の金武店から空港は遠いのでここで空港に向った。 この旅はここで終わり。東京もどってビール飲んで寝た。

RubyKaigi2024 @沖縄

2024-05-14 23:59:59 +0900

沖縄だったのでいってきました。

Day 0

開始日の前日、この日に沖縄に入りました。この日は15:30発の飛行機にしました。 これはこの日の夜のイベントに参加するための時間にしたつもりでした。 つもりとは、今回 RubyKaigi ではプレチェックインが19:00まで行なわれているのをメールでもらい、 急遽 RubyKaigi 会場へ寄ることにしました。 プレチェックインでは、沖縄気分な格好をして行ったのですが、それ以上に沖縄楽しみにしてる格好のひとが居てびっくり。 チェックインを済ませて宿へ行き荷物を置いて船上パーティへ。 この帰りに二次会へ山羊刺しがある居酒屋へ行きました。

Day 1

みたセッションは以下になります

  1. Writing Weird Code
  2. The grand strategy of Ruby Parser
  3. Strings! Interpolation, Optimisation & Bugs
  4. Namespace, What and Why
  5. Ractor Enhancements, 2024

Writing Weird Code

本年は三日間平日だからか Matz のキーノート開始ではなく、ぺんさん ではじまりでした。うんまあ、ひとつひとつの話はわかるんだけど、どうしてそうなるのかわからないことをたくさん話されました。

The grand strategy of Ruby Parser

ことしは(も?)パーサー元年な発表だった。パーサーギャング の親分こと 金子さん の発表で、去年の発表のあとどのように開発をし、これからどのような機能を開発していくのか、今回でどんな形になったのかを話してくれました。

Strings! Interpolation, Optimisation & Bugs

Namespace, What and Why

@tagomorisさんの全 rubyist1 待望の機能である Namespace の思想、実装の話です。 似た機能として Refinments があるのですが 機能として分かれているのも便利そう。 Namespace で区切ることでライブラリがより便利に、より安全に利用できそうでした。

Ractor Enhancements, 2024

Ractor のお話。

オフィシャルパーティー

オフィシャルパーティーは波の上うみそら公園のビーチでBBQ(BBQエリア)とパリピだった。

Day 2

  1. Leveraging Falcon and Rails for Real-Time Interactivity
  2. Does Ruby Parser dream of highly expressive grammar?
  3. Embedding it into Ruby code
  4. Reducing Implicit Allocations During Method Calling
  5. It’s about time to pack Ruby and Ruby scripts in one binary
  6. Running Optcarrot (faster) on my own Ruby.
  7. Lightning Talks

Leveraging Falcon and Rails for Real-Time Interactivity

サミュエル の Async を使うことによって速くするにはの話。

Does Ruby Parser dream of highly expressive grammar?

@ydah_ さんの発表。もともと見る予定ではなかったが、前日の発表を見てしまったので興味が出てきたので聴くことに。

Embedding it into Ruby code

みようと思ってたが、ランチ出るまでに時間が掛かりすぎてすこししか見れていない。

Reducing Implicit Allocations During Method Calling

研鑽 Ruby プログラミング の著者ジェレミーの発表。

It’s about time to pack Ruby and Ruby scripts in one binary

@ahogappa0613 さんの発表で Ruby のプログラムを配るために One Binary にプログラムを梱包していくという発表でした。 One Binary を作る方法として、現在ある Ruby プログラムを静的リンクしてコンパイルして配る方法を採用していました。 この方法は Ruby 自体を書き替えるのが十分少なく行えそうなので期待できそうです。

Running Optcarrot (faster) on my own Ruby.

今年個人的 No.1。@isshiki1969 さんの発表で、 Ruby の Rust での実装だと聞いていたので楽しみにしていました。 聞いているとどうも Rust だけで作ってるわけじゃないぞとなっており、一部 Assembler でも作成されているようです。 必要な機能は実装されているようでしたが、まだ Ruby on Rails 動いていないようです。 とても速いので面白そうでした。

Lightning Talks

前の発表が楽しすぎて少し遅れてはいりました。

夕飯とカラオケ

この日の夕飯は会場近くで色々なディナー、パーティーが企画されてたのですが、どうしても行きたいディープな沖縄へ行きたかったのでそちらへ。 栄町市場のべんり屋 玉玲瓏へ行き、餃子を食べてきました。 帰りに RubyKaigiKaraoke が丁度いい時間だったので2曲ほど歌ってました。 だいたい22時ころに翌日発表する人主催のボドゲ会がはじまり、1時ごろ退出しました。

Day 3

聞いたセッションは以下です。前日の RubyKaigiKaraoke ではしゃいで疲れてるので記憶が曖昧です。

  1. Ruby Committers and the World
  2. YJIT Makes Rails 1.7x Faster
  3. Speeding up Instance Variables with Red-Black Trees
  4. From LALR to IELR: A Lrama’s Next Step
  5. Make Your Own Regex Engine!
  6. Matz Keynote

Ruby Committers and the World

いつもどおりの感じが戻ってきた感じのセッションでした。ここで GVL2 が出てとくに盛り上がってましたね。個人的に GVL を外してもはやくならないと思っていますが、無い状態での実行したときどのような挙動をするのか、はやくするにはどうするのか興味があります。この議論で Linux のメンテナーをやってる小崎さんが賛成してくれてたのでとても心強いなと。

YJIT Makes Rails 1.7x Faster

国分 さんの YJIT で Rails を動かすと速くなったという話。 タイトルに偽りがあり、曰く発表当日には1.8倍高速化されたそうです。

Speeding up Instance Variables with Red-Black Trees

アーロン の発表。インスタンス変数 のデータ保持方法を赤黒木で行う話でした。 赤黒木の説明を行い、どう実装していくかを日本語でやってくれました。

From LALR to IELR: A Lrama’s Next Step

コバジュン の発表。 現在、Lrama を LALR パーサーから Scannerless パーサー を動かすために IELR パーサー に変更している話でした。

Make Your Own Regex Engine!

藤波 さんの発表で、正規表現エンジン を Ruby で作る話。 意外と小さくできるようでおもしろそうな感じでした。

Matz Keynote

今年は Ruby4 の話が出てきました。 Namespace が実装されて動けば Ruby4 になるそうです。ガンバレモリスさん。 あと明確に AOT コンパイラー が欲しいと言っていました。

owari

今年も楽しいセッションが盛り沢山で休む暇がなく、全部たのしかったのですが、英語力と体力が足りないのを痛感しております。 セッション間の立ち話も興味深いのも多く、休みとはと思いながら過しておりました。


  1. プログラミング言語 Ruby が好きな人たちのこと。 ↩

  2. Giant Virtualmachine Lock の略。これがあるから遅いと主張している人たちがいる。 ↩

Sway 用 Window 切り替えを作った

2024-05-11 23:59:59 +0900

あたらしく PC 買って、 Linux の GUI 環境を X11 から Wayland に乗り変えることにしました。 いままで利用していたデスクトップ環境を i3 から sway に変更しました。 最近利用していた macOS や i3 ではあまり気にしていなかったのですが、Windows の Alt+Tab での ウインドウ切り替えが便利だったのを思い出したのでこの便利な機能を模倣することにしました。

でも本当にほしいのは Alt+Tab の順番に切り変わるやつではなく、アクセスしたいウィンドウへの切り変えなのです。 そこでこの機能を ruby で実装することにしました。

準備

準備として以下のソフトウェアがインストールされていることを期待しています。

  • window manager: i3/sway
  • launcher/menu program: wofi

作成

なにかしら実装あるだろうということで参考を探していたら見付けたのでその実装を参考にします。 プログラムは以下になります。

#!/usr/bin/env ruby

require 'bundler/inline'

gemfile do
  source "https://rubygems.org"
  gem "i3ipc"
end

require "i3ipc"
require "open3"

class SwayWindowSwithcer
  def self.switch = new.switch
  def initialize
    @conn = I3Ipc::Connection.new
    @workspaces = @conn.workspaces
    @windows = Set.new
    set_windows
  end
  def switch = @conn.command("[con_id=#{@windows.to_a[open].to_h[:id]}] focus")

  private
  def list_window = @windows.map(&:name)
  def displays = @conn.tree.nodes.reject { |display| display.name == "__i3" }
  def open
    Open3.popen3(['wofi', '-i', '-k', '/dev/null', '-d'].join " ") do |i, o, _e, _w|
      i.puts list_window.join("\n")
      i.close
      list_window.index(o.read.strip)
    end
  end

  def set_windows
    displays.map do |display|
      display.nodes.map { |workspace| @windows += workspace.nodes }
    end
  end
end

SwayWindowSwithcer.switch

i3 は IPC が定義 されています 1 。 今利用している sway は i3 の wayland 向け実装なので IPC に互換性があります。 そのまま i3ipc 関連のライブラリを利用することが可能です。 ということで今回は ruby の gem として i3ipc.gem というそのままのやつがあったので利用します。 i3 で起動しているウィンドウ一覧を取得して、名前を wofi に渡します。 ウィンドウ一覧を受け取った wofi は切り替えたいウィンドウを絞り込み、選択ができます。 切り替えたいウィンドウを選択したら、今度は i3 へ選択したウィンドウへのフォーカスする命令を送ります。

ここで注意点として、二つありひとつ目は以下があります。 ruby の i3ipc は I3Ipc::Connection からでしかコマンドを送れないです2。 そのためこのプログラムでは @conn.command でコマンドを送るとします。 このままではどのウインドウかはわからないので i3 コマンドを送る際に [con_id=id] を付けます。 今回はウィンドウを切り替えることをしたいだけなので [con_id=id] focus とします。 ふたつ目はシステムの ruby を利用する際には必要な gem がシステムにインストールされている必要があります。 もしインストールされていないのであれば手動でいれる必要があります3。

おわり

あたらしい PC を買い、デスクトップ環境を替えました。 あたらしい環境で少し不便だったところを解消するプログラムを書いてみました。


  1. InerProcess Communication ↩

  2. 参考にした Python はウィンドウのオブジェクトから直接コマンドが送れます。 ↩

  3. root ユーザーで一度実行するか、手動でやる必要がある。インラインとはいったい…… ↩

いいかんじに Bundler で管理されていない Gem を使いたい

2023-11-16 23:59:59 +0900

前回作成した irb-theme-dracula を bundler で gem が管理されているプロジェクトで利用したい。 利用したいが、そのままでは利用できないです。 これは gem が bundler で管理されているので、 Gemfile に書いていない gem は利用できないです。

対処案

bundler で管理されていない gem をどうしても利用したい場合は以下のような方法が考えられます。

  1. :100: Gemfile に追加: 正攻法。ただ複数人で開発しているなどの場合色付けだけの機能で追加するのかというと…
  2. :+1: 古きよき方法: setup.rb を利用して、対象 gem の必要ファイルをインストールする。
  3. :poop: 実行する Ruby の $LOAD_PATH に gem のパスを追加: 強引にパスを追加して require することで解決。

ということでそれぞれ方法をみてみましょう。

Gemfile に追加

正攻法ですね。便利で全員が使い、必要なら追加しましょう。 どうしても利用したい場合でプロジェクトの Gemfile に書きたくない場合はプロジェクトを管理しているバージョン管理システム にコミットしないなどオペレーションを行いましょう。 管理方法が大変なのでこの方法はないなと。

古きよき方法

rubygems が生まれる前の方法をとりましょう。ここでは setup.rb で site_ruby に必要なファイルをインストールしてくれます。 便利なやつです。

使い方

$ gem install setup # gem でイントールします。
# インストールしたい gem のリポジトリをコピーなどして手元にもってきましょう。
$ cd /path/to/install/gem
$ setup.rb install # gem のインストールが行なわれます。
$ cd /path/to/your/project
$ bundle exec ruby your/scrip.rb

これでできるのですが問題点があり、この方法では利用したいプロジェクト以外でも利用できてしまうので特定のプログラムだけで site_ruby を読み込むとかしていいかんじに使い分けるには少し工夫が必要です。 全部の Ruby プログラムで利用したい訳ではないのでこの方法については断念。

実行する Ruby の $LOAD_PATH に利用する gem のパスを追加

この方法は単純で、プログラム側で必要なファイルを読み込む時のみ利用する。 利用するファイル(require "irb/theme/dracula/light" を書いているファイル)で利用したい gem へのパスを $LOAD_PATH へ追加します。 $LOAD_PATH への追加方法としては以下の方法があります。

  1. 環境変数 ($RUBYLIB) に指定: 環境変数を利用するごとに指定することができる。
  2. 実行時に指定: 実行時に -I/path/to/gem を ruby の引数に利用可能。利用するごとに指定する必要がある。
  3. 実行ファイルで指定: 設定ファイルを読み込んで実行するような場合では楽。

ここでは 実行ファイルで指定 する方法を見ていきましょう。

実行対象のプログラムは irb です。 irb は ~/.irbrc を読み込んで起動するため、 ~/.irbrc に以下のような設定を書きます。

# Reline 0.4.0 以上に対応した irb のバージョンチェック
if Gem::Version.new(IRB::VERSION) >= Gem::Version.new("1.9.0")
  # gem のインストールされるパスを取得。rbenv を利用している場合は以下
  # preview 判では version に previewX や 0 がついたりするので * を付与し、検索
  ld_path = File.join(ENV["RBENV_ROOT"], "versions", RUBY_VERSION + "*", "lib", "ruby", "gems", RUBY_VERSION.sub(/\d+$/, "0*"), "gems")
  # 読み込む gem 対象のパスを取得
  gem_path = File.join(Dir.glob(File.join(ld_path, "irb-theme") + "-*").last, "lib")
  $LOAD_PATH.unshift(gem_path) # LOAD_PATH に追加
  $LOAD_PATH.uniq! # LOAD_PATH に追加した重複してた場合削除
  require "irb/theme/dracula/light"
end

この設定を書いたら Ruby を 3.3.0-preview3 以上にして bundle exec irb と実行してみましょう。

かった!

おわり

gem は入ってるけど、プロジェクトで利用できないなあとおもい使えるようにしたいということでやってみました。 今回の irb は Ruby 2.2 以下だとデフォルトでインストールされているのでそもそも Reline の新しいバージョン(0.4.0)をサポートしていないのこの方法を利用してみました。

irb の補完の色がいじれるようになったのでかっこよくしてみた

2023-11-08 23:59:59 +0900

Reline が 0.4.0 になり、タイトルのとおり irb で補完画面の色を好きなように変更できるようになりました。

変更できるようになったので dracula 風のテーマを gem としてリリースしました!!!! リポジトリは以下です!!!

katsyoshi/irb-theme-dracula - GitHub

インストール

ということで使いかたを。まずは gem i irb-theme-dracula で インストール します。 ダーク と ライト を作りました。 ダーク は明るい コンソール 向けに、 ライト は暗い コンソール 向けに作っています。 インストール後は irbrc ファイルに require "irb/theme/dracula/dark" か require "irb/theme/dracula/light" を追加。

irb を実行し、補完をしてみましょう。まず、irbrc ファイルになにもかかないデフォルトの場合は以下

次に ダーク の require "irb/theme/dracula/dark" を書いた場合は以下

最後に ライト require "irb/theme/dracula/light" の場合は以下

おわり

irb も便利になってカスタマイズができるようになりました。色とか考えたくないひとは gem にして一発で決まるようにすると便利ですよ。たぶん。

新しいキーキャップ手にいれたよ!!!!

2023-06-27 23:59:59 +0900

最高だったイベント 第一回keebkaigi 行った影響で、キーボードをいじりたくなりました。 今利用している corne cherry でかなり満足しているため、 新規につくるとかはあまりやる気はないので、見た目(キーキャップ)や触った感じ(キースイッチ)を替えようかとおもいます。

見た目と触った感じ

見た目の変更としてキーキャップを海外のサイト Drop.com や 遊舎工房 から買いました。 買ったのは以下の4つ!

SA プロファイル1 が好きでいつものように遊舎工房へ行ったら展示品でアルファベットだけのを見つけたので即購入。 一つだけだと寂しいので、なんとなく Drop.com を眺めていたら、 SA プロファイル でいくつか安くなっていたので購入。 現時点では、MAXKEY SA Purple と DOMIKEY ABS Doubleshot SA Cyberpunk Pumper を市松模様に交互にキャップをはめて使っています。

触った感じの変更として キースイッチ を Talp Keyboard で買っています。

もともとは リニア と呼ばれるタイプの キースイッチ3 が好きでしたが、感触が最近飽きてきたので、 タクタイル と呼ばれるタイプの キースイッチ を利用するようになっています。さらに最近は重めの方が好きなのかもしれないという状況です。 Durock T1 Shrimp をどこか4で見かけたので購入。見た目もよく、タクタイルだったので結構気に入ってます。 KTT Matcha と KBDiy hp type は Durock T1 Shrimp が corne cherry の バックライトLED がきつく感じはじめたので購入。 KTT Matcha をしばらく利用してたのですが、タクタイル でもちょっと音が気になるのと、軽すぎる感じでした。 音が気になったので今時点では KBDiy hp type を利用しています。この キースイッチ は少し重いです。

ついでに TRRS ケーブル を変更しました。これは アマゾン でてきとうに

おわり

気分転換にキーボードのキースイッチとキーキャップ変更とを行ってみました! 自作キーボードはいいぞ。


  1. 背が高いプロファイルや統一された高さなど様々なプロファイルがあります。キーキャップに関することのくわしくは 自作キーボード温泉街の歩き方 の キーキャップの湯のお誘い ver2 を参考にしてください。 ↩

  2. 2023/6/30 時点、 Talp Keyboard では販売終了。 ↩

  3. 音が鳴るようなタイプやクリック感があるようなタイプ様々なタイプがあります。くわしくは 遊舎工房 のキースイッチの説明 を参考にしてください。 ↩

  4. たぶん twitter.com で @takkanm か @talpkeyboard のついーと。 ↩

Zellij はじめました

2023-06-19 23:59:59 +0900

はい。タイトルの通り、 Zellij をはじめてみました。 切っ掛けは以下のツイートを見つけたので。

というっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっことでね、はじめます。

Zellijとは?

Rust 製の tmux クローン。 はやってますね Rust 。

Install

つかってるのが Gentoo Linux なので portage からもはいります。

$ sudo emerge zellij

他の OS やソースコードからのインストール方法は公式から見て入れてください。

Customize

tmux のクローンとあり、カスタマイズもかなりできるようです。 とりあえず、起動してみましょう。

$ zellij

デフォルトでもナビがあり、簡単に利用できて便利です。が、キーバインドが気に食わないので変更しましょう。 といってもカスタムするファイルを書いていませんでしたね。初期設定を標準出力に zellij setup --dump-config で出せるので リダイレクト なり、 コピペ なりでファイルを作りましょう。保存先はどこでもいいのですが、標準で読み込んでくれる $HOME/.config/zellij/config.kdl がいいでしょう。ファイル形式は KDL となっていますがなんんもわからん。

keybinds clear-defaults=true {
  shared {
    bind "Ctrl g" { SwitchToMode "Normal"; }
  }
  normal {
    bind "Ctrl t" { SwitchToMode "Tmux"; }
  }
  tmux {
    bind "c" { NewTab; SwitchToMode "Normal"; }
    bind "o" { FocusNextPane; SwitchToMode "Normal"; }
  }
}

keybinds でキーバインドの設定がデキルのですが、 clear-defaults=true を指定してあげることで デフォルト のキーバインドを消すことができます。モードがたくさんあり、そのモードに対してそれぞれキーバインドを設定することができます。上記の例では、Normal モードで Ctrl t を押すと、Tmux モードに入ります。ここで、c を入力すると新しい tab で Shell が動きます。今どのモードに居るのかわからなくなっても必ず Normal モードへ Ctrl g で戻れるように shared に設定してあります。 こんな感じで設定は簡単にできます。

おわりに

かんたんに zellij の現在(2023/6/20 バージョン 0.36.0 で確認。最新バージョンは 0.37.0。)の設定をみてきました。カスタムできるのはキーバインドだけじゃなく、カラースキーム、レイアウトなどなど様々に変更できるので御参考までにーーーー。 ねむい。

趣味はvaporware造りです v.0.0.1

2023-05-25 23:59:59 +0900

RubyKaigi2023に行ってきたのは別エントリにしたのでこのエントリでは LT で話しした内容の説明などをしていこうかと思います。

Presentation

LT申し込みまで

RubyKaigi2023 松本でやるし発表もしたいが、ネタがないなとおもってたら本編の方の CFP1 が閉じられてた2。 とはいえ今年は COVID-19 の制限も無くなるから LT あるとおもうので LT 出せたらいいなあと考えてた。 そうこうしているうちに Ruby30th で今はまだないものだけど…って matz がいったものを造ろうとなりました。

LT の応募サイト開くまでにネタが幸い見つけることができ、実装をはじめることにした。

実装

ということで、通るかどうかわからないですが、発表できるように準備をはじめました。 準備といっても実際は実装どこまでできましたーというような発表にする予定だったので そのまま実装をしています。

実装予定は発表にもあった通り、以下の予定ですすめて、最後に fiddle で読み込めるように実装していました。

  1. 四則演算: Integer の計算ができること
  2. 変数: 変数が使えること
  3. 制御構文: for や if などの基本的な制御構文が使えること
  4. メソッド: メソッドが定義でき、利用できこと

を目標に実装をすすめていましたのでそれぞれの進捗を

四則演算

とくに詰まる点もなく、AST をもとに assembler へ変換するだけでいけた。

変数

これが一番大変だった。教科書 を cherry-picking しながら進めてたために、 実装でわからん部分が出てきたのでインターネット介して gdb リモートデバッグの講習を受けながら実装。 もともとここか制御構文までで終わるだろうなあと予想してたが、SEGV 出しながらもなんとかくりあ。

制御構文

はじめは素直に if 文を実装。ここも上記の理由によりなんもわからんとなり、別の人の実装 を参考に実装。 if 文だけじゃつまんないというか、とくになにもできないのでループ文を追加しようとしました。 はじめは for 文を実装しようと考えましたが、なんとここで重大なことに気がつきました。 Ruby の for のことはなにもしらない。ということに。そういえば for x in 1..10; puts x;end とか書けるけど そもそも Range クラスや Array 作る必要あるよな?ということで一旦 for はやめに。

ということでここは while 文を実装して、fibonacci 数 を求めることができるようになりました。

メソッド

ここは変数、制御構文ができれば作るだけなら問題はなかったように思えます。 ただほんとうに作るだけだったので、引数なし、定数を返すだけのメソッドの確認しか行なっていないです。 ここの実装にたどり着くとは思っておらず、最後のRubyKaigi直前の6連休に入ってから実装できてしまったので あんまりブラッシュアップできていないです。 引数の扱い、変数の利用、などなど確認をとれておらずにいますが動いたので fiddle で読み込めるように。

Fiddle で利用できるようにする

定義したメソッドを C言語 の関数として見えるようにしてあげればいいので、 そうしたら、あっさりとうごいてしまった3。この時点で連休の終わりの方だったのは覚えている

発表準備

もともとGW前の連休には実装を終らせてGWの連休中に発表資料作成とできたところまでの実装のブラッシュアップを 行なう予定でしたが、目標の実装が見えてるとなるとどうしても実装したくなって実装の方を進めてました。

もともと発表は Rabbit を利用して英語で行う予定でしたが、LTはとくに うちあわせのために資料を先に出すとかなかったのでとりあえず日本語で作成しました。 実装おわっていないというか実装に時間掛けすぎたのと、RubyKaigiへ持っていくPCをあたらしくしたので 冒険はできずに素直に Google スライド 利用して作成、 後日 Rabbit で清書するということにしました。

発表資料自体は 5/8 or 5/9 ぐらいに作成し終っていました。デモなしで発表練習するとちょうど時間通りに おわるのでこの資料作成完了時点ではこれでよしとしてました。 この時点でも資料はすくたなくとも英語にしようとは考えて資料は作成していました。

当日

当日の朝、資料作成というか資料の英語変換をやっていて、やっているうちに 実際発表してなにができてなにができてないみたいなこと言ったとしても なにがなんだかわからんよなとなったので急遽デモをやって、実行できること示すように少し変更しました。

当日はセッションききながらかなり緊張していました、直前のセッションのトラブルもあったので。 聞いた人はわかるとおもうのですが、発表が途中でおわったのはこういった事情があったのでああいう発表になりました。

後日

発表当日の昼飯時に、 @ukstudio が cookpad のイベントとして 手を動かして振り返る RubyKaigi 2023 が5/18にあるからきてよと誘われたのでいくことにしました。 この会では、デキテイナカったデモを最後までやりきっています。

書き直し

手を動かして~ のあとに Rabbit への清書を行ないました。 いままでもいくつかの発表は Rabbit でやってたのですが、 Rabbit テーマ を作りたい作りたいと思っていたので今回は時間もあるのでつくることにしました。 とはいってもほぼ @yu_suke1994 のリポジトリをコピーしただけなんでうが……

まとめ

RubyKaigi の LT で話ししたことをまとめました。 実装の話はもうちょっと詳しく書きたいけど、そもそも実装もすすめたいしでなかなか書けていないですね。

次回作もご期待ください 完


  1. Call For Proposal。ずっと Call For Paper だとおもってたので知ったときえってなった。 ↩

  2. 2023-01-31 締切で完全にネタない状態だった。 ↩

  3. もともとの発表予定ではここまでしかできなかったんですよーって濁す予定でしたが思っている以上に実装がすすんでしまった。 ↩