ESM アジャイル事業部 開発者ブログ

永和システムマネジメント アジャイル事業部の開発者ブログです。

0 1 1 2 3 5 8 13 21 34 55 ...

こんにちは!健康のために1日1万歩の散歩を始めたら、雨に打たれて風邪をひいた@haruguchiです。

RubyKaigi 2024 が終わって早くも2カ月が経とうとしています。私にとってのKaigi Effectはなんだろうと考えると、言語処理系やコンピュータサイエンスといった別のレイヤに興味を持ったことだと思います。特に今年の@tompngさんの発表「Writing Weird Code」ではWeird Codeを書くということの楽しさを感じたり、テストの追加や言語仕様を深く理解するのに役立つことを実感しました。

弊社ではQuine部*1なるものが発足され、熱量十分の状態です。そこで私も業務ではまず書かない Weird Code を書いてみたので紹介します。

ラムダ計算でフィボナッチ数列を出力する

ラムダ計算は関数を主体とした計算モデルの一つでチューリング完全であることが知られています。 今回はフィボナッチ数列の第0項から第10項*2までの計算を、Rubyのlambda式を用いてシミュレートしていきます。

ここで、断っておくとラムダ計算自体は決してWeird Code ではなく計算の意味論だったり、型理論に使われたり、関数型プログラミングの論理的な土台となっていたりします。ラムダ式のみで書かれたコードが見た目上奇妙に見えるという意味で Weird Codeとして紹介します。

本体

コードの全容はこちらをご参照ください。 ラムダ計算でフィボナッチ数列を計算する · GitHub

本体だけ抜粋すると以下のようになります。

# 本体(50文字折り返し)
proc =
  ->k{->f{->f{->x{f[->y{x[x][y]}]}[->x{f[->y{x[x][y]
  }]}]}[->f{->l{->x{->g{->b{b}[->p{p[->x{->y{x}}]}[l
  ]][x][->y{g[f[->l{->p{p[->x{->y{y}}]}[->p{p[->x{->
  y{y}}]}[l]]}[l]][x][g]][->l{->p{p[->x{->y{x}}]}[->
  p{p[->x{->y{y}}]}[l]]}[l]][y]}]}}}}][k][->x{->y{->
  f{f[x][y]}}}[->x{->y{x}}][->x{->y{x}}]][->l{->x{->
  l{->x{->x{->y{->f{f[x][y]}}}[->x{->y{y}}][->x{->y{
  ->f{f[x][y]}}}[x][l]]}}[l][f[x]]}}]}}[->f{->x{f[->
  y{x[x][y]}]}[->x{f[->y{x[x][y]}]}]}[->f{->m{->n{->
  b{b}[->m{->n{->n{n[->x{->x{->y{y}}}][->x{->y{x}}]}
  [->m{->n{n[->n{->p{p[->x{->y{x}}]}[n[->p{->x{->y{-
  >f{f[x][y]}}}[->p{p[->x{->y{y}}]}[p]][->n{->s{->x{
  s[n[s][x]]}}}[->p{p[->x{->y{y}}]}[p]]]}][->x{->y{-
  >f{f[x][y]}}}[->s{->x{x}}][->s{->x{x}}]]]}][m]}}[m
  ][n]]}}[m][n]][->x{->l{->x{->x{->y{->f{f[x][y]}}}[
  ->x{->y{y}}][->x{->y{->f{f[x][y]}}}[x][l]]}}[f[->n
  {->s{->x{s[n[s][x]]}}}[m]][n]][m][x]}][->x{->y{->f
  {f[x][y]}}}[->x{->y{x}}][->x{->y{x}}]]}}}][->s{->x
  {x}}][->s{->x{s[s[s[s[s[s[s[s[s[s[x]]]]]]]]]]}}]][
  ->n{->f{->x{f[->y{x[x][y]}]}[->x{f[->y{x[x][y]}]}]
  }[->f{->n{->b{b}[->n{n[->x{->x{->y{y}}}][->x{->y{x
  }}]}[n]][->x{->s{->x{x}}}][->b{b}[->n{->n{n[->x{->
  x{->y{y}}}][->x{->y{x}}]}[->m{->n{n[->n{->p{p[->x{
  ->y{x}}]}[n[->p{->x{->y{->f{f[x][y]}}}[->p{p[->x{-
  >y{y}}]}[p]][->n{->s{->x{s[n[s][x]]}}}[->p{p[->x{-
  >y{y}}]}[p]]]}][->x{->y{->f{f[x][y]}}}[->s{->x{x}}
  ][->s{->x{x}}]]]}][m]}}[n][->s{->x{s[x]}}]]}[n]][-
  >x{->s{->x{s[x]}}}][->x{->m{->n{n[->n{->s{->x{s[n[
  s][x]]}}}][m]}}[f[->n{->p{p[->x{->y{x}}]}[n[->p{->
  x{->y{->f{f[x][y]}}}[->p{p[->x{->y{y}}]}[p]][->n{-
  >s{->x{s[n[s][x]]}}}[->p{p[->x{->y{y}}]}[p]]]}][->
  x{->y{->f{f[x][y]}}}[->s{->x{x}}][->s{->x{x}}]]]}[
  n]]][f[->n{->p{p[->x{->y{x}}]}[n[->p{->x{->y{->f{f
  [x][y]}}}[->p{p[->x{->y{y}}]}[p]][->n{->s{->x{s[n[
  s][x]]}}}[->p{p[->x{->y{y}}]}[p]]]}][->x{->y{->f{f
  [x][y]}}}[->s{->x{x}}][->s{->x{x}}]]]}[->n{->p{p[-
  >x{->y{x}}]}[n[->p{->x{->y{->f{f[x][y]}}}[->p{p[->
  x{->y{y}}]}[p]][->n{->s{->x{s[n[s][x]]}}}[->p{p[->
  x{->y{y}}]}[p]]]}][->x{->y{->f{f[x][y]}}}[->s{->x{
  x}}][->s{->x{x}}]]]}[n]]]]}]][->s{->x{x}}]}}][n]}]

これは全てRubyのlambda記法によって表現されています。 このコードは奇妙さを演出するためにスペースを削除したり50文字で折り返して人間にとって読みにくいものになっています。なので、ラムダ式を意味のまとまりに区切り定数に代入してみます。すると以下のようになります。

# natural number(必要のない数も存在する)
ZERO     = -> s { -> x { x } }
ONE      = -> s { -> x { s[x] } }
TWO      = -> s { -> x { s[s[x]] } }
THREE    = -> s { -> x { s[s[s[x]]] } }
FOUR     = -> s { -> x { s[s[s[s[x]]]] } }
FIVE     = -> s { -> x { s[s[s[s[s[x]]]]] } }
TEN      = -> s { -> x { s[s[s[s[s[s[s[s[s[s[x]]]]]]]]]] } }
FIFTEEN  = -> s { -> x { s[s[s[s[s[s[s[s[s[s[s[s[s[s[s[x]]]]]]]]]]]]]]] } }

# bool
TRUE = -> x { -> y { x } }
FALSE = -> x { -> y { y } }

# if
IF = -> b { b }

IS_ZERO = -> n { n[-> x { FALSE }][TRUE] }
IS_ONE = -> n { IS_ZERO[SUB[n][ONE]] }

# pair
PAIR = -> x { -> y { -> f { f[x][y] } } }
LEFT = -> p { p[-> x { -> y { x } }] }
RIGHT = -> p { p[-> x { -> y { y } }] }

# operator
SUCC = -> n { -> s { -> x { s[n[s][x]] } } }
SLIDE = -> p { PAIR[RIGHT[p]][SUCC[RIGHT[p]]] }  # ペア型を引数に取り、右の値と右の値+1したペア型のデータを返す
PRED = -> n { LEFT[n[SLIDE][PAIR[ZERO][ZERO]]] }
ADD = -> m { -> n { n[SUCC][m] } } # n + m
SUB = -> m { -> n { n[PRED][m] } } # n - m

# z-combinator
Z = -> f { ->x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }

# list
EMPTY = PAIR[TRUE][TRUE]
UNSHIFT = -> l { -> x { PAIR[FALSE][PAIR[x][l]] } }
IS_EMPTY = LEFT
FIRST = -> l { LEFT[RIGHT[l]] }
REST = -> l { RIGHT[RIGHT[l]] }

# comparable
IS_LESS_OR_EQUAL = -> m { -> n { IS_ZERO[SUB[m][n]] } }

RANGE = Z[-> f {
  -> m { -> n {
    IF[IS_LESS_OR_EQUAL[m][n]][
      -> x { UNSHIFT[f[SUCC[m]][n]][m][x] }
    ][
      EMPTY
    ]
  } }
}]

# 畳み込み演算
FOLD = Z[-> f {
  -> l { -> x { -> g {
    IF[IS_EMPTY[l]][x][
      -> y {
        g[f[REST[l]][x][g]][FIRST[l]][y]
      }
    ]
  } } }
}]

# map
MAP = -> k { -> f { FOLD[k][EMPTY][-> l { -> x { UNSHIFT[l][f[x]] } }] } }


def to_nat(nat)
  nat[-> n { n + 1 }][0]
end

def to_bool(bool)
  IF[bool][true][false]
end

def to_ary(proc)
  ary = []

  until to_bool(IS_EMPTY[proc])
    ary << FIRST[proc]
    proc = REST[proc]
  end

  ary
end

# フィボナッチ数列の漸化式
FIB = Z[-> f {
  -> n {
    IF[IS_ZERO[n]][
      -> x { ZERO }
    ][IF[IS_ONE[n]][
      -> x { ONE }
    ][
      -> x {
        ADD[f[PRED[n]]][f[PRED[PRED[n]]]]
      }
    ]][ZERO]
  }
}]

proc = MAP[RANGE[ZERO][TEN]][-> n { FIB[n]} ]
results = to_ary(proc).map { to_nat(_1) }
p results #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

とても読みやすくなったのではないでしょうか。順を追ってみていきましょう。

自然数を表現する

今回作ったのはフィボナッチ数列の第0項から第10項までを計算するラムダ計算です。計算結果は自然数で表されますが、ラムダ計算では関数しか登場しないので関数を自然数(チャーチ数)に対応づける必要があります。

# natural number
ZERO     = -> s { -> x { x } }
ONE      = -> s { -> x { s[x] } }
TWO      = -> s { -> x { s[s[x]] } }
TEN      = -> s { -> x { s[s[s[s[s[s[s[s[s[s[x]]]]]]]]]] } }

引数sをxに何回適用するかを自然数に対応づけています。例えばs[x]であれば1回の関数適用があるので1を表し、s[s[s[x]]]であれば3回関数適用されているので3を表します。これで理論上100でも1000でも自然数を表すことができます。(大変ですが、、、)

これを私たちが普段扱っている数として視認できるように変換メソッドも併せて定義しておきます。

def to_nat(nat)
  nat[-> n { n + 1 }][0]
end

to_nat(ZERO) #=> 0
to_nat(TEN) #=> 10

条件式を表現する

ラムダ計算はチューリング完全なのでbool値や条件分岐IFも表すことができます。 bool値に関しては2つの引数をとり、前者を返すのをtrueと表し、後者を返す関数をfalseで表します。

# bool
TRUE = -> x { -> y { x } }
FALSE = -> x { -> y { y } }

# if
IF = -> b { b }

IFは非常にシンプルで引数であるbをそのまま返す恒等関数になっています。 それゆえ、IF[condition][consequnce][alternative]のような使い方ができます。

# 簡約の様子
IF[TRUE][ONE][THEREE]
          ↓
TRUE[ONE][THREE]
          ↓
ONE

IF[FALSE][ONE][THREE]
          ↓
FALSE[ONE][THREE]
          ↓
THREE

IFはこのままではELSIF節を表せませんが、ELSIFを表すときにはIFを入れ子にして対応します。また、bool値においてもラムダ計算では関数で表されているので値(true, false)に変換するメソッドを作っておきます。

def to_bool(bool)
  IF[bool][true][false]
end

ペア型のデータ構造を表す

データ構造も関数で表すことができます。ここでは2つの値の組みを表すペア型のでデータ構造を作っていきます。また、ペア型のデータの左の値と右の値を取り出す関数も実装します。

# pair
PAIR = -> x { -> y { -> f { f[x][y] } } }
LEFT = -> p { p[-> x { -> y { x } }] }
RIGHT = -> p { p[-> x { -> y { y } }] }

算術演算を表す

フィボナッチ数列の任意の項を求める場合、2つの数(に対応付けられたラムダ式)の足し算をする必要があるためラムダ式の世界の算術演算を導入する必要があります。任意の自然数*3に対し、次の自然数を取得するSUCCと前の自然数を取得するPREDそして、足し算を表すADD、引き算を表すSUBを作ります。 掛け算や、割り算も同じように実装することができますが、フィボナッチ数列の計算では使わないので割愛します。

# operator
SUCC = -> n { -> s { -> x { s[n[s][x]] } } }
# ペア型を引数に取り、右の値と右の値+1したペア型のデータを返す
SLIDE = -> p { PAIR[RIGHT[p]][SUCC[RIGHT[p]]] }
PRED = -> n { LEFT[n[SLIDE][PAIR[ZERO][ZERO]]] }
ADD = -> m { -> n { n[SUCC][m] } } # n + m
SUB = -> m { -> n { n[PRED][m] } } # n - m

SUCCではs[...]...の中のn[s][x]に分けると考えやすいです。s[]は関数適用1回分で、n[s][x]は関数sをxでn回呼び出すという意味になり合計n+1回の関数適用になります。よって次の値の自然数を表すことになります。

またここからn[●][○]という形式がよく出てきますが、●を○でn回適用すると読み替えると理解しやすいです。

引き算に関するラムダ式(PREDやSUB)は少し難しいです。n回関数適用したときにn-1を表すような関数を作るためにはペア型のデータ構造をうまく使います。SLIDEというペア型を引数に取り、ペア型の右の値とそれに+1した値のペア型を返す関数を用意します。

PREDのLEFT[n[SLIDE][PAIR[ZERO][ZERO]]]の部分を見るとSLIDEを引数PAIRでn回適用していることがわかるので例えば6という数に対してPREDを適用するとイメージとして以下のようになります。

# イメージ
n = 6
n[SLIDE][PAIR[0][0]]

1[SLIDE][PAIR[0][0]] → (0, 0 + 1) → (0, 1)
2[SLIDE][PAIR[0][0]] → (1, 1 + 1)  → (1, 2)
...
6[SLIDE][PAIR[0][0]] → (5, 5 + 1)  → (5, 6)

# ペア型の左の値を取り出す
LEFT[6[SLIDE][PAIR[0][0]]] → 5

もちろん実際には数に対応付けられた関数を取り出すのであくまでイメージです。 1増やしたり、1減らしたりできるようになったら nを引くことは1減らすをn回適用するという感じでADDSUBを作ることができます。

またここで <=のような比較演算子で必要最低限のものを実装しておきます。

# comparable
IS_LESS_OR_EQUAL = -> m { -> n { IS_ZERO[SUB[m][n]] } }

今回扱っている数は自然数(0含む)のみなので引き算が負の数にならないことを利用し0かどうかを判定しています。

Z-コンビネーターを表す

Z-コンビネータとは不動点コンビネータの一種で  \displaystyle
f(g(f)) = g(f)
となるような性質を持ちます。

# z-combinator
Z = -> f { ->x { f[-> y { x[x][y] }] }[-> x { f[-> y { x[x][y] }] }] }

これを用いることで無名再帰を実装することができます。 余談ですが、不動点コンビネータには Yコンビネータというものもありますが、Rubyの場合 Yコンビネータを用いることができないことに注意してください。Yコンビネータの場合無限ループに陥ります。 コンビネータについての詳しい解説はここでは割愛します。詳しくは、Jim Weirichの以下の動画をご参照ください。

www.youtube.com

リストを表現する

リストというデータ構造が必要になってくるのでここで用意します。 このコードでは、ペア型のデータ構造を用いて2つの値を組にしています。これを利用して、値と次の値へのポインタを格納した連結リストを構築します。この連結リストでは、各ノードが次のノードへの参照を持つことで、データの順序を保持しながらリスト全体を構成しています。

# list
EMPTY = PAIR[TRUE][TRUE]
UNSHIFT = -> l { -> x { PAIR[FALSE][PAIR[x][l]] } }
IS_EMPTY = LEFT
FIRST = -> l { LEFT[RIGHT[l]] }
REST = -> l { RIGHT[RIGHT[l]] }

次のようにデータを構築します。

list = UNSHIFT[
  UNSHIFT[
    UNSHIFT[EMPTY][THREE]
  ][TWO]
][ONE]

# イメージ
# [ONE, TWO, THREE]

またこれを可視化するためにto_aryというメソッドを用意します。

def to_ary(proc)
  ary = []

  until to_bool(IS_EMPTY[proc])
    ary << FIRST[proc]
    proc = REST[proc]
  end

  ary
end

p to_ary(list).map { to_nat(_1) }
#=> [1, 2, 3]

次に範囲を表すRANGEを実装します。

RANGE = Z[-> f {
  -> m { -> n {
    IF[IS_LESS_OR_EQUAL[m][n]][
      -> x { UNSHIFT[f[SUCC[m]][n]][m][x] }
    ][
      EMPTY
    ]
  } }
}]

考え方としてはrange(a, b)の場合、aからbまでの全ての要素を再起的にリストに追加しています。また、終端まで繰り返すため先ほど作成したZコンビネータを使っています。

続いて、MAPを実装するための準備として畳み込み演算(FOLD)を実装しておきます。

# 畳み込み演算
FOLD = Z[-> f {
  -> l { -> x { -> g {
    IF[IS_EMPTY[l]][x][
      -> y {
        g[f[REST[l]][x][g]][FIRST[l]][y]
      }
    ]
  } } }
}]

リストが空だったら初期値xを返し、そうでない場合は関数gを再起的に呼び出します。

畳み込みを実装したのでMAPは簡単に記述することができます。

# map
MAP = -> k { -> f { FOLD[k][EMPTY][-> l { -> x { UNSHIFT[l][f[x]] } }] } }

MAPは引数を2つ取ります。kが元のリストでFOLDを使って畳み込みを行っています。また2つ目の引数fは適用する関数を表しています。

フィボナッチ数列の計算を表す

以上で、フィボナッチ数列を計算するのに必要な役者が揃いました。 フィボナッチ数列は

 \displaystyle
n: 自然数(0を含む) \\\ a_{0} = 0, a_{1} = 1, a_{n+2} = a_{n} + a_{n+1}

という漸化式で表されます。これをもとに実装すると以下のようになります。

FIB = Z[-> f {
  -> n {
    IF[IS_ZERO[n]][
      -> x { ZERO }
    ][IF[IS_ONE[n]][
      -> x { ONE }
    ][
      -> x {
        ADD[f[PRED[n]]][f[PRED[PRED[n]]]]
      }
    ]][ZERO]
  }
}]

proc = MAP[RANGE[ZERO][TEN]][-> n { FIB[n]} ]

FIBはフィボナッチ数列の任意の項の計算になっています。 条件分岐が3つ入っており、漸化式の通りの計算を行います。

procの部分はMAP関数を使って計算結果をリストに格納している処理です。

先ほど定義したラムダ式(関数)を数やデータ構造に変換するメソッドを群を適用すると結果が得られます。

result = to_ary(proc).map { p to_nat(_1) }
p result #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

今回は第0項から第10項までのフィボナッチ数列を計算しましたが、任意の数をラムダ式で表しRANGE関数に渡すことで任意の項までの計算ができます。ただし、Rubyのプログラムで実行すると関数呼び出しが多くコールスタックがオーバーフローします。(RUBY_THREAD_VM_STACK_SIZEという環境変数でスタックサイズを変更できます)

まとめ

RubyKaigi 2024に参加した私のKaigi Effectとしてラムダ計算のみでフィボナッチ数列を計算するというWeird Codeに挑戦しました。本当はラムダ計算を使ってQuineを作れないか考えたのですが、うまくできそうになかったので個人的な宿題にしたいと思います。


永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

*1:Quineに限らない超絶技巧プログラミングについてワイワイします。

*2:0-indexedに合わせるため初項を第0項としています

*3:ここでは自然数に0を含める立場を取っています。

Rails / OSS パッチ会 2024年7月のお知らせ

2024年7月の Rails / OSS パッチ会を 7月10日(水)に Discord でオンライン開催します。

この会をひとことでいうと、日頃のお仕事で使っている Rails をはじめとする OSS について、upstream にパッチを送る会です。

会には Ruby と Rails のコミッターである顧問の a_matsuda もいますので、例えば Rails に送るパッチのネタがあるけれど、パッチを送るに適しているかの判断やパッチを送る流れが悩ましいときなど a_matsuda に相談して足がかりにするなどできます。

開催時間は 17:00-19:00 となりますがご都合のあう方はぜひご参加下さい。

Discord の Rails/OSS パッチ会サーバーへの招待 URL は以下です。

discord.gg

今後予定されている地域Ruby会議や各種プロポーザルに思いを馳せながらという雰囲気になると思います。

rubykaigi.org

これからパッチ会に参加してみたいという方、OSS 開発者間の会話に興味があるので聞いてみたいという方もお気軽にどうぞ。


永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

Ruby Hack Challengeはじめました

こんにちは。構文解析器研究部員のS.H.です。

アジャイル事業部内ではじめたRuby Hack Challengeについて紹介します。

Ruby Hack Challengeとはなにか?

元々はRubyコミッターのko1さんがCookpadで開催されていたRubyの内部をハックするイベントです。 Rubyの内部実装を読んだり、Cのコードを変更して新しいメソッドを追加したりとRubyをより身近に感じられるイベントです。

techlife.cookpad.com

github.com

それを社内向けに勉強会として始めてみました。

はじめたきっかけ

元々、ko1さんたちが開催されていたRuby Hack Challengeに何度か参加していました。 また参加していく中で「Rubyをハックできる人を増やしたい」なという思いがあり、そこで僕がオーガナイザーをしているHamada.rbでもforkとして開催していました。

また、Hamada.rbで開催していた時に溜まっていたノウハウが社内向けに活用できそうだったことと、「社内Ruby Hack Challengeやりたいな」と元々思っていたことなどもあり、Kaigi Effectで一気にやる気に火がついた勢いで始めました。

やっている内容

基本的にはRuby Hack Challengeのチュートリアルをベースに進めています。

github.com

また参加者にMacを使っている人が多いので、Mac向けのビルド手順なども別途用意したりしています。

初回はRubyのビルドを行い、全員がminirubyが動くところまで進みました。

minirubyがビルドでき、実行できたところ

また余談としてUniversal Parser を有効化する方法なども紹介しました。

今後

当面はRuby Hack ChallengeのチュートリアルをベースにRubyの内部実装の話をしつつ、独自メソッドの追加などのハックをしていきたいと思います。

個人的な野望としては、「Ruby本体にパッチを送れる人を増やしていきたいな」と思っているのでゆるく長く続けていければと思います。


永和システムマネジメントでは、Rubyのハックを通じてコミュニティと成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

LR Parser Night w/ Asakusa.rb をアンドパッドさんと共催します

こんにちは。構文解析器研究部員の @junk0612 です。

After RubyKaigi 2024 LR Parser Night w/ Asakusa.rb というイベントを、アンドパッドさんのオフィスで共催します。普段は島根にいる @S.H. 研究部員も現地登壇します!

andpad.connpass.com

大まかな流れとしては、LR_parser_gangs の4人が集まって、1人5分のトークをしたあとに and the World っぽいパネルディスカッションをする予定です。

各メンバーのトーク内容は募集ページに載っている以上の情報を僕も知りませんが、それぞれの立場からの面白い発表が聞けそうです。乞うご期待。

パネルディスカッションについては、いまのところ @hsbt さんに司会役をお願いして、いくつかのトークテーマについて話す予定です。参加者の Rubyist が知りたそうなテーマをなんとなく考えていますのでお楽しみに。もし聞いてみたい話題があれば、僕まで DM などで連絡をいただけると考慮できたりできなかったりするかもしれません。

それでは当日、会場でお会いしましょう!


永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

Rails / OSS パッチ会オンライン 2024年6月のお知らせ

2024年6月の Rails / OSS パッチ会を 6月19日(水)に Discord でオンライン開催します。

この会をひとことでいうと、日頃のお仕事で使っている Rails をはじめとする OSS について、upstream にパッチを送る会です。

会には Ruby と Rails のコミッターである顧問の a_matsuda もいますので、例えば Rails に送るパッチのネタがあるけれど、パッチを送るに適しているかの判断やパッチを送る流れが悩ましいときなど a_matsuda に相談して足がかりにするなどできます。

開催時間は 17:00-19:00 となりますがご都合のあう方はぜひご参加下さい。

Discord の Rails/OSS パッチ会サーバーへの招待 URL は以下です。

discord.gg

先月開催された RubyKaigi 2024 の感想戦や、今後予定されている地域Ruby会議に思いを馳せながらという雰囲気になると思います。

rubykaigi.org

RubyKaigi 2024 で OSS 熱の高まっている方や、これからパッチ会に参加してみたいという方、OSS 開発者間の会話に興味があるので聞いてみたいという方もお気軽にどうぞ。


永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

Scrum Fest Kanazawa 2024に永和システムマネジメントから3名が登壇します

2024年7月19日(金) から 20日(土) にかけて開催される Scrum Fest Kanazawa 2024 に永和システムマネジメントから @fkino, @rei_moco_, @koic の3名が登壇します。

www.scrumfestkanazawa.org

2024年7月20日(土) に登壇する弊社メンバーのスケジュールとタイトルは以下です。

また初日の7月19日(金) 18:00-18:20 の Platinum スポンサーセッションでは、弊社 Agile Studio メンバーによるトークがあります。

現地チケットはすでに売り切れとなっておりますが、オンラインチケットは販売中です。お時間のあう方はぜひ遊びに来てください。

confengine.com


株式会社永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと共生しながら成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

RubyKaigi 2024 に参加しました && 初登壇してきました

こんにちは。@junk0612 です。 今回は、RubyKaigi 2024 の参加記と、自分が初めて登壇した感想、および裏話を少しお届けしようと思います。

登壇以外の参加記

Day0

11:35 HND → 14:20 OKA の飛行機で沖縄へ移動しました。初めて空港ラウンジを利用してみたり、待機スペースで同便の Rubyist のみなさんにお会いしたりなど、RubyKaigi の機運の高まりを感じました。やや余談ですが、@kasumi8pon が土曜日から前入りしていて、場所も考えるとかなりアリな選択肢だったなあとちょっと後悔したりしました。来年はどうしよう。

今回は otoge.rb1 の会合がバスで30分かかるラウンドワンで行うしかなかったためスケジュールがタイトになってしまい、行脚はつけられたものの正直音ゲー欲は全然発散できなかったです……

夜は弊社主催の Night Cruise でした。生憎の天候でしたが、完全な立食にせず座れる場所を残しておいたおかげで、参加者同士でゆっくり交流を深めていただいていた様子が観測できてよかったです。イベントの準備 && 会場の下見にも行った @fugakkbn@haruguchi お疲れ様でした!

パーサーについて話していたテーブルのようす

その後はパッチモンスターこと @nobu さんを誘って2次会に行ったり、〆ステーキ食べるぞと思って行った店が営業時間外で若干グダったりしつつ、自分は 1:30 くらいに宿に帰った気がします。

Day1

前日のうちに check-in を済ませておいたおかげでスムーズに会場入りし、@tompng さんの Keynote を聞きました。やっぱり意味がわからなかった。いやなんというか、一応 Ruby を仕事にして8年くらい経つはずで、おかげで個々に使われているテクニックは説明されればわかるようになってきましたが、作品のアイディアは何を食べたら思いつくのかもわかりません。社内で Quine 部が立ち上がったので、来年の TRICK に向けて勉強させていただこうと思います。でもあんまりパーサーいじめないでね……

そして次が、Lrama 勢としては見逃せない The Bison Slayer こと @yui-knk さんのセッションでした。一言で言えば Parser Keynote でした。全編を通して理解が追いつかなかったところはさすがになかったのですが、逆に言えば金子さんの情報整理とか言語化が巧みだったので、引っかかることなく聞けてしまったということなのでしょう。30分ずっと LT のペースで喋り続けたら守礼門の画像も休憩用に入れたくなるってもんです。

そして、Official Party の会場で Lrama のコミット権をもらいました。

パーサーについて話していたテーブルで Lrama のコミット権をもらったようす

その後、クラフトビールが美味しいお店に2次会で行きました。このとき一緒にいた @ydah さんが翌日発表のプレッシャーからか一言も喋らず黙々と飲み続けていて、大変そうだなあと思っていました2。結局自分は、3次会で @yasulab さんはじめいろんな方と合流→ステーキヒカルで〆て帰りました。

Day2

@ydah さんの発表を聞きに行きました。作ったもの (Parameterizing Rules) の面白さとか便利さを伝えたいという思いが随所ににじんでいた発表だったなあと思いました。これからもよろしくお願いします! @hasumikin さんの発表@koic の発表@S.H. とパーサー界の黎明卿こと @yui-knk さん2名を含むLT と、パーサー関連の発表がこの日は多かったですね。

日中は発表前の誰かを見つけては「緊張してんスか???大丈夫っスよー、頑張ってください」って9割煽って1割励ますセリフをずっと言ってた気がします。

夜は Leaner さんの YAKINIKU を食べつつ、パーサーについて話してました。

その後カラオケに行きましたが、事前に Discord でボドゲの募集があったため、全く歌わずにボドゲをやっていました。たしか遊んだのは『支離滅裂』と『グッズメイカー』です。

プレイヤーを変えつつ何回か回していたら24時を回ってしまい、さすがに翌日発表の身で最後までいるのもなぁ、ということで切り上げ、大人しくホテルに帰って寝ました3

Day3

無事にすっきり起床し、Ruby Committers and the World を最前列で見ました。今年は進行の上手さもあってか特に面白かった気がします。隣に座った @katsyoshi さんとああだこうだ言いながらだったのもよかったのかも。

見たあとはさすがに緊張からかそわそわしてしまって他の発表を見る気になれず、廊下の椅子で発表練習して通りがかった @m_pixy に「緊張してんの??」とにやにやされたり、@ima1zumi さんに会ってお昼休憩中に通訳の方と打ち合わせなんですよ、と話したら「じゃあ今からお昼食べてきたらいいんじゃないですか?」と言われてなるほどと思って早めのお昼に繰り出したりしました。

お昼は最初に国際通り入口の A&W を見に行ったんですが修学旅行生でごった返していて打ち合わせまでに戻れなそうだったので、結局会場近くの「三丁目そば」で食べました。待ってるところでたまたま隣に座った @shutooike さんに声をかけていただいたんですが、打ち合わせの時間が迫ってきていて大したお話ができず……。頼んだ「冷やしそば」も好きな味で美味しかったのに、味わっている暇がなかったのが悔やまれます。

戻って通訳さんとの打ち合わせを済ませ、またそわそわ会場をうろついては出会った知り合いに緊張をぶつけることを何回か繰り返したら、そもそもなぜ緊張しているのかわからないことに気がつき、不思議とそれで緊張がほぐれました。やってやるぞ、という気持ちになりました。

発表後は、 @ydah さん、@sylph01 さんと、会場の隣にあったビアカフェでプチ打ち上げをし、Matz keynote を聞きに行きました。前のほうが空いてれば分かれて座ろうかなと思っていたのですが @sylph01 さんが一緒に座りたがるので、どうしたんだろうと思いつつ後ろの隣り合った席で Closing まで聞いていたら、来年の会場が松山と聞いて合点がいきました4。誘致お疲れ様でした、そしてローカルオーガナイザー業頑張ってください。個人的には道後温泉本館と紅プリンセスがかなり楽しみです。

終わったあとは歩いて After Party の会場へ。途上で Ginza.rb の復活の話を聞いたり、会場で「聞いてなかったけどどんな話したんですか」と言われたので嬉々として PC を取り出してダイジェストトークをしたり、@kokuyouwind さんにボドゲの話をしつつ Error tolerant なパーサーの参考になりそうな HTML5 に関する論文を紹介してもらったり、パーサージェネレーターに興味があるという方がいたので無限にパーサーの話をしてみたりなどいろいろありましたが、項目が長くなってきたのでそれぞれ詳しくは直接聞いて下さい。

さらに Ruby Music Mixin に @sylph01 さんと @UVB_76 さんが DJ として参加するということで聞きに行きました。セトリ良かったです。めっちゃノれた。翌日の予定があったので無理をしないところで帰ろうとしたら松田さんが外にいて、たしか @hand_accident さんと3人でステーキヒカルで〆て終わりにしました。

Day(4..)

土曜日は予定通り、レンタカーを借りて妻と一緒に美ら海水族館に行ってきました。朝早く起きて行くのは無理だろうと想定していたので、お昼前にレンタカーを借りて途中でご飯を食べつつ向かいました。楽しかったです。映画館っぽい作りでジンベエザメの水槽を見られる部屋があって、順路からちょっとそれる関係か全然人がおらず、ゆったり見られてよかったです。

惜しむらくは、時間が足りなくて本館を見るだけで閉館時間になってしまいイルカやマナティーは見られなかったのと、近くのビーチで遊んでいたらレンタカーの返却予定時間をオーバーしてしまったのが残念でした。那覇市内じゃなく名護の方に宿を取ればよかったなあとちょっと思っています。

戻ったあと、残っていそうな Rubyist に Twitter で絡みに行ったら、飲み会をやってるとのことで座標をいただき、しかもホテルから近かったので妻と2人でお邪魔してきました。余談ですが、こういうところに連れて行っても全く躊躇しないどころか「話はわかんなかったけど面白かったよ」と言ってもらえるので大変ありがたい……

翌日飛行機で戻ってきたのですが、週明けから喉に異変があり、火曜夜に発熱しました。もともと水曜日は休みの予定だったのですが病院へかかったところコロナ陽性と診断され、その週はまるまるダウンする羽目になりましたとさ。

初登壇の感想

昨年 Lrama にコントリビュートを始めてから、RubyKaigi 2024 での発表を短期目標として活動してきたので、なんとかやりおおせてよかったです。ただ、そのためにやや無理をしている時期もあったのが正直なところなので、頑張ればここまでやれることがわかったうえで、今年以降はもっと持続可能な生活スタイルを模索していきたいです。

もちろん改善点はありますが、発表としては満足する出来になったなと思っています。直接フィードバックをもらうのも、感想ブログを読むのもとても楽しいです。

もっと緊張するかなあと思っていたのですが、それなりに界隈歴が長くなり、地域Ruby会議とかで発表経験を積んできたおかげか案外大丈夫でした。発表中に手が震えていると喋ってしまったものの PC 操作にまごつくほどではなかったし。

あと、参加者の人たちとコミュニケーションを取るときに、自分の発表があるおかげで話のネタに困らないのは助かるなという発見もありました。発表するっていいもんですね。

スライド・登壇の裏話

スライドはこちらです。その他裏話は箇条書きでその下にあります。

speakerdeck.com

  • 実は CFP 提出後、枠が足りないので @ydah さんとマージしてもらえないか、という依頼がありました。最終的には枠が分かれて話すことになりましたが、「去年は金子さんが1人でりゅうおうを倒した。今年は II にあたるので、マージしても3人で登壇しよう」と @ydah さんと会話したのが、スライドの区切りにドラクエ名言集を入れた理由の一つです5
  • 今回は発表の難易度設定として「あまり詳細な解説は入れず、絶対に話したい内容をまず入れて、余った時間で話せる範囲で解説を入れる。RubyKaigi なので、ある程度置いてけぼりになったほうが楽しんでくれるはず」というつもりでスライドを作りました。狙い通りの反応になったかなとは思っていますが、やや時間が余ったのは反省点ですね。
  • 普段はわりと引っ張りがちですが、今回は事前提出が必要だったのも相まって過去最高にスムーズにスライドの準備ができました。もちろん前日まで細かい調整はしましたが、発表者ノートも含めていったん全部作り終えてから沖縄入りしています。ちょっと自分でも信じられません。
  • Google スライドで作っていたのですが、発表者ノートを表示しながらプレゼンテーションモードにするとブラウザの枠が消えず全画面表示にならないという問題が接続確認時に見つかり、ちょっとバタバタしていました。おかげで会場の様子を撮り忘れ、発表時間タイマーのリセットも忘れて今何分か正確にわからないという事態になりました。なんとかなってよかった。
  • 特に RubyConf Taiwan 以降、妻には迷惑をかけっぱなしだったのでスライドに謝辞を入れましたが、通訳さんからも打ち合わせのときに「奥様との旅行楽しんできてくださいね」と言われたのはちょっと面白かったです。
  • スライドづくりの最中に現実逃避としてエディタを vim から neovim に移行したのですが中途半端なので、これからしばらくはキーボード探しとあわせて設定を弄り倒していきたいです。
  • パーサーギャングの親分こと @yui-knk さんから Ruby Music Mixin で「悔しい」という最大級の賛辞をもらえたので大満足です。

終わりに

大変な長文になってしまいましたが、いかがでしたでしょうか。発表でも触れた通り IELR は lex_state の牙城を崩すための準備に過ぎないので、これからも頑張っていきます。LR_parser_gangs の次回作にご期待ください!

永和システムマネジメントでは、kaigieffect でパーサーをやってみたくなった部員候補Ruby とアジャイルソフトウェア開発を通じてコミュニティと成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp


  1. Rubyist の音ゲーマーでゲーセンに遊びに行く会合です。詳しくは ruby-jp slack の #music_game か ruby-jp discord の #otogerb へどうぞ。
  2. 本人は2次会までで帰りましたが、誰とどこで飲んだか全く覚えていないそうです……
  3. というのは実は嘘で、資料の確認をしたり任意の SNS を見たりしてしまい、寝たのは3時頃でした。
  4. 後で聞いたところによると、ちょうど自分が旅行で四国に行って松山で sylph01 さんと会った 2022/11 ごろ、松田さんも会場視察に来ていたそうです。ニアミス。
  5. もちろん僕がドラクエ大好き人間なのも多分にあります。一番好きなのは VII でしたが、XI をプレイしてから XI になりました。僕のアイコンは昔六本木にあったルイーダの酒場に飾られていたロトの剣の写真です。