Type Ruby Concept
Money Forward Fukuoka Advent Calendar 2025 23日目です。
yiyenene と申します。
Ruby と型システム
不穏な話をしたいわけではないですが、Ruby における静的型付けの議論は長い間行われています。私は rbs が好きですが、全く書けていません。やはり実装を書き終わった後に(あるいは書く前に)別のファイルにわざわざ定義を書くという行為をさせるにはかなり強い動機が必要になると思います。
rbs-inline はそういう意味では良いアプローチだと思っていて、同じファイル内で宣言が済む、となれば書いてあげてもいいかなと思う人もより多く出てくるでしょう。
ですがコメントを書くという行為も極端に言えば不要なはずの行為であり、手間が増えてしまっています。やはり言語として書いたものから必要な情報が抽出されるほうが自然です。そのためには言語自体に型付けの情報が含まれるようになった上で、それを活用できるほうが嬉しいですよね。
Concept
ということで最小限ではありますがコンセプトモデルを作ってみました。
以下のような文法で書かれた trb ファイルを rbs-inline のコメントがついた rb ファイルに transplie するというコンセプトです。
class Greeter
attr_reader name: String
attr_reader age: Integer
def initialize: (name: String, age: Integer) -> void
@name = name
@age = age
end
def greet: () -> String
"Hello #{name}! I'm #{age} years old!"
end
end
let greeter = Greeter.new(name: 'typed ruby', age: 0)
pp greeter.greet
↓ transpliled
class Greeter
attr_reader :name #: String
attr_reader :age #: Integer
#: (name: String, age: Integer) -> void
def initialize(name:, age:)
@name = name
@age = age
end
#: () -> String
def greet
"Hello #{name}! I'm #{age} years old!"
end
end
greeter = Greeter.new(name: 'typed ruby', age: 0)
pp greeter.greet
ruby にそのまま引き渡して実行するとこんな感じ。
> trb run examples/hello.trb
"Hello typed ruby! I'm 0 years old!"
ruby であるために何が必要か
型付きであることが開発者体験を良くする例としてはコンパイル時の警告であったりエラーであったりだと思います。このコンセプトではこのような例を作りました。
let test = 'test'
test = 100
pp test
> trb run examples/warning.trb
Warning at line 2, column 1: Type mismatch for variable 'test'.
Expected: String
Found: Integer
Variable was declared at line 1, column 1.
100
型が付いていると言ってもいろいろあって、このケースはエラーでしょ?とか let でなく const にしてそもそも再代入を禁止すべきでしょ?とかこの例だけ見てもいろんな考え方ができると思います。
ruby の現在の仕様は様々な議論を経た上で ruby であるために取られている選択だと思います。typed ruby を作るとしてそれをどれだけ尊重するか、またはしないかのバランスが一番難しいところのように思います。
個人的にはこのケースの場合はエラーではなく、警告として気づきを与えるという選択が良いのではないかと思いました。設定で選べるようにするのもいいかもしれません。
ruby らしい楽しさとか懐の広さを保ちつつ、より有用な情報を提供できてこそ意味がある、ような気がします。
いかがでしたか?こんなプログラミング言語もあっていいんじゃないでしょうか?
仕様策定を進めてもう少しいろいろ動くようになったら面白いかもと思いつつ、今のところはこの先全く未定です。
それではお先に失礼します。
Discussion