00:00:09.719
Okay.
00:00:10.840
Hello, I’m Soutaro Matsumoto, and I will be presenting.
00:00:15.679
I think the title is a bit confusing, especially for this year. I'm afraid that some of you might be expecting a presentation about the new syntax in Ruby 3.2, but that’s not what this is about.
00:00:26.240
The discussion will be centered around writing your RBS type declarations inside the Ruby code.
00:00:34.360
I want to start with a quick demonstration. This code is a simple example with no type definitions. As you can see, there is no definition for the Talk class, which causes an error saying that it cannot find the declaration of the constant Talk.
00:01:02.640
Let’s start by adding the class definition. Once the type definition is updated, the Talk constant is detected, but it doesn't have the initialize method. So, the default new method is used, which accepts no arguments.
00:01:24.640
The type checker reports an issue regarding the arguments. We can correct this by adding the initialize method with three arguments.
00:01:36.399
Then, we can write the types of variables using the RBS syntax. This adjustment changes the types of the method arguments. For instance, we can specify that the first argument of the initialize method is a String, and we can add type annotations for the other parameters.
00:02:01.039
To clarify, the second parameter is a Date, and the third is an array of Strings. However, currently, we are passing a String instead of an array, which needs to be addressed.
00:02:42.800
Next, we need to add some attributes. We use the double colon syntax to define the type of the attributes, along with a few additional attributes.
00:03:11.200
We can then implement the initialize method, which assigns the title to the @title instance variable.
00:03:30.679
Today’s presentation is about how you can incorporate RBS type declarations inside your Ruby code. To introduce myself further, I’m Matsumoto, one of the Ruby contributors, and I’ve been working on the RBS type definitions since April.
00:04:02.120
Many of you likely attended the sponsor presentation this morning, so you may already be familiar with my work.
00:04:37.919
This is how we use type checking. We need to maintain two sets of files: Ruby code files that include the implementation, and RBS files that contain the type definitions of your program. On the left is the Ruby code, while on the right is the RBS type definition.
00:05:12.280
The type checker will verify the consistency between the two. As you can see, in this instance, the method ‘speakers’ has an underline indicating that there’s a type error.
00:05:50.000
The type definition for ‘speakers’ indicates it always returns a Speaker object, but it calls an array method that returns nil when the speakers array is empty.
00:06:28.440
This design choice of separating the type definition files from implementation files isn’t common in today’s modern statically typed languages like Java or Swift.
00:06:50.720
In such languages, you typically don’t write type definitions in separate files like header files in C or C++. However, we chose to do it this way in Ruby for specific reasons.
00:07:15.240
One primary reason is to avoid extending Ruby syntax for type annotations. We decided against modifying the Ruby syntax to allow embedding type information in the code.
00:07:59.760
Additionally, there were technical concerns regarding the implications of adding new syntax without breaking compatibility, as Ruby’s syntax can be quite complicated.
00:08:38.200
If we want to avoid extending Ruby syntax, we could merely place types in string remarks. However, I wanted to avoid this because string remarks are frequently used in Ruby code to represent actual data.
00:09:10.080
I don’t want to mix static type information with runtime data that’s essential for program execution.
00:09:35.440
The best approach I found was through metaprogramming. This metaprogramming allows defining Ruby programs without specific syntaxes, like class or def syntax.
00:10:11.760
For example, it’s possible to create a class without using the conventional class syntax.
00:10:42.080
But this can make it quite challenging to track the structure of the Ruby code due to the complexity of metaprogramming.
00:11:10.440
Another problem arises when there is no class syntax or def syntax in Ruby code, which leads to challenges in declaring their types.
00:11:37.920
To address this, I decided to put type information in a separate file because it is not actual code, allowing us to define a concise and clear syntax without worrying about potential conflicts.
00:12:15.679
This allows for a shift in semantics, as we can keep everything static within the RBS files without the need for metadata or method definitions using Ruby syntax.
00:12:52.800
Yet, there are benefits to having separate files for type definitions.
00:13:34.200
The RBS files included in many of my gems serve to clarify the structure of the Ruby code, making it easy to read. There are clear modules, attributes, and methods, allowing one to focus more on the program’s overall outline rather than implementation details.
00:14:35.600
We need to declare the types of expressions; if we can implement a good mechanism to embed type declarations in Ruby, we can simplify the coding process.
00:15:16.240
However, this cannot be applied to classes defined in extensions, which have a different syntax as they are written in C or other languages.
00:15:55.359
Thus, these are some reasons for introducing RBS files for type checking, though there are some challenges involved.
00:16:20.520
The most obvious difficulty is that switching between files during development can be cumbersome. You need to jump between Ruby source files and RBS files.
00:17:26.760
This requires maintaining two sets of files, which can be tedious and lead to synchronization issues.
00:18:09.440
For example, when starting development on a class, you’ll write the Ruby code and the RBS file. However, the real issue arises when trying to delete a method; you must remove it from both the type definition and the implementation.
00:19:39.120
This can lead to mistakes where one might forget to delete one of the entries, creating unnecessary clutter in the codebase.
00:20:01.120
Additionally, while reviewing pull requests, we require type information to effectively evaluate the changes.
00:20:22.560
If a pull request only modifies the method signatures, we may miss this information due to the lack of visibility into the definitions.
00:20:53.599
Having the type of the ‘command location’ method included would greatly assist in catching potential issues.
00:21:24.160
I wanted to stress that type checking in Ruby is an optional feature; you can choose to ignore it entirely if you wish.
00:21:58.200
However, I believe there are advantages to utilizing the types. With the increasing adoption of RBS, I want to encourage everyone to adopt types more vigorously.
00:22:35.040
Stronger connections between the code and types will enhance overall code quality.
00:23:14.160
I released the RBS inline gem, which allows you to write type definitions directly in your Ruby code.
00:24:04.560
This gem enables you to embed RBS type declarations as comments within your Ruby code, making it convenient.
00:24:40.000
The comments are processed by the RBS inline tool, which reads the code to detect type annotations and generates corresponding RBS files.
00:25:22.679
Using this gem means you don’t have to maintain two sets of files; the focus can remain on editing and reading your Ruby code.
00:26:04.960
The RBS inline gem extracts embedded type definitions into RBS files, allowing you to validate the correctness of both implementations and type definitions.
00:26:46.760
The RBS syntax supports various constructs and can provide annotations on parameters, return types, and more, making type definitions more manageable.
00:27:29.520
We continue to explore better ways to implement RBS inline syntax. Feedback has been incredibly valuable as we work towards a more refined solution.
00:28:09.160
I invite anyone interested to join the discussions on GitHub regarding feature requests and potential improvements.
00:28:48.480
We aim to embed RBS type declarations directly into Ruby code to enhance the development experience.
00:29:10.440
I will be available for a small meeting with contributors during the afternoon break today, so feel free to join me for further discussions.
00:29:40.305
Thank you.