Type Annotations

Summarized using AI

Ruby Programming with Type Checking

Soutaro Matsumoto • May 31, 2018 • Sendai, Miyagi, Japan

The video titled 'Ruby Programming with Type Checking' features a presentation by Soutaro Matsumoto at RubyKaigi 2018. In this session, Matsumoto discusses Steep, a type checker for Ruby that was introduced in the previous year. As an experimental tool, Steep aims to provide a gradual typing system for Ruby, allowing developers to add type annotations to their code. Here are the main points covered in the video:

  • Introduction to Steep: Matsumoto presents Steep, highlighting its capabilities for local type inference and structural typing, compared to another Ruby type checker, Sorbet.
  • Development Progress: He reports on the improvements made in the nine months since the last presentation, including the release of versions 0.2.0 and 0.3.0, while still considering the tool experimental and not ready for production.
  • Type Annotations: Steep enables type annotations inline with Ruby code, which simplifies the coding process, although explicit annotations are required for certain structures.
  • Comparison with Sorbet: Matsumoto discusses the differences between Steep and Sorbet, particularly around their subtyping methodologies; Steep uses structural subtyping for type assessments, while Sorbet employs nominal subtyping.
  • Demonstration of Type Checking: A live demonstration showcases how Steep detects type errors in simple Ruby programs. Matsumoto builds a 'Presentation' class and a 'Speaker' class, emphasizing correct type definitions and methods.
  • Application in Real-World Scenarios: He elaborates on the unique challenges of applying type checking in Rails applications, which heavily utilize metaprogramming, requiring a tailored approach to define and validate types.
  • Challenges and Future Developments: Matsumoto notes issues faced in the type checking process, such as the lack of support for common type libraries in Steep, and discusses the roadmap for improving type inference and type library integration.
  • Conclusions and Q&A Session: The speaker concludes by emphasizing the importance of explicit type declarations for ensuring code correctness in Ruby's dynamic environment. He addresses a question from the audience regarding the decision against automatic type inference, underscoring the need for programmer awareness of type declarations.

In summary, the presentation provides insights into the functionality of Steep as a type checker in Ruby, illustrating the balance between explicit types and the dynamic nature of Ruby programming, while paving the way for future enhancements.

Ruby Programming with Type Checking
Soutaro Matsumoto • May 31, 2018 • Sendai, Miyagi, Japan

Last year, I had a presentation to introduce Steep, a type checker for Ruby. However, the implementation is so experimental that it cannot be used for production at all.
In this talk, I will report the nine months progress of the project and share the experience how the tool helps Ruby programming.

RubyKaigi 2018 https://rubykaigi.org/2018/presentations/soutaro

RubyKaigi 2018

00:00:00.030 Hello everyone. Last year, during the RubyKaigi in Hiroshima, I presented my idea on how we can introduce type checking to Ruby. At that time, I had a preliminary implementation, which was more of a proof of concept than a fully developed tool. This type checker is called Steep, and it serves as a gradual typing system for Ruby.
00:00:14.809 Steep allows you to write type annotations in Ruby, similar to comments, but currently, there is no type inference for certain aspects of the code. For the structure of modules, you must provide type annotations explicitly. However, it does allow for local type inference, meaning you can write Ruby programs without needing to annotate every single local variable. In terms of structure, the typing system in Steep primarily focuses on the types of objects. It incorporates features like union types and intersection types. For example, it supports subtyping relations between union types based on their structural properties. Unfortunately, the tool is still experimental.
00:01:06.300 Recently, I released a new version of Steep—version 0.3.0. Just a couple of days prior, I released 0.2.0. There have been numerous improvements over these past nine months. In this presentation, I want to explain some of these advancements. However, since my time is limited to 40 minutes, I'll focus more on demonstrating how Steep can assist in Ruby programming.
00:01:37.800 First, I'd like to show a quick comparison between Steep and Sorbet, another Ruby type checker. Both tools allow for local typing and share certain system features, such as generic union types. However, the main difference lies in their handling of subtyping: Steep utilizes structural subtyping, while Sorbet uses nominal subtyping. Nominal subtyping requires explicit naming of types, whereas structural subtyping assesses the structure of the types instead.
00:02:17.940 When defining types and method signatures in Steep, you can provide type annotations directly in your Ruby code. For instance, in a given Ruby file, you can use special method calls to indicate types for class variables. The type annotations are written in a way that allows the compiler to check them against the defined types.
00:02:50.700 A notable difference is that Steep performs fast type checking, while Sorbet is relatively slower. This performance difference can largely be attributed to the implementation language: Steep is written in Ruby, while Sorbet is implemented in C++. As a result, the overhead of checking subtyping relations structurally can impact performance.
00:03:32.230 I would now like to dive into a demonstration. Let's start with a very simple Ruby program that consists of only two classes. Initially, I'll show how Steep catches type errors in basic operations. For example, if we try to add a string to an integer, Steep will flag this as an objection since it mandates that only integers should be added.
00:04:13.380 Next, let’s complicate things a bit by creating classes and checking them with Steep. I’ll define a 'Presentation' class with attributes such as title and speaker, along with their respective types. The presentation will initialize with two keyword arguments—title and speaker, and it will have a method to print information about the presentation.
00:05:06.510 To clarify the structure, we can also define accessor methods for the title and speaker without having to annotate the instance variables every time. Notably, how instance variables are defined in the class’s signature matters; it is essential for correct API behavior, as these variables might be referenced elsewhere.
00:06:00.000 Following this, I’ll implement the 'Speaker' class, incorporating fields for name and GitHub URL, where the GitHub URL is optional. We'll ensure that the methods defined here properly handle the data types expected and return the correct values. This feedback from Steep helps ensure type correctness throughout our classes.
00:06:44.890 Now, moving onto testing, I will demonstrate how to utilize these classes in a broader context. We will be able to instantiate a presentation and check if the types are correct, revealing potential issues with our definitions and ensuring we align with the expectations set by Steep.
00:07:28.670 In conclusion, I have demonstrated the functionalities of type checking in small Ruby programs, showing how defining these signatures correctly can lead to better type safety. The steps involved include writing the signature, implementing the logic, and testing with Steep’s type checker to ensure accuracy continuously.
00:08:55.790 I have also delved into type checking real-world applications, specifically a Rails application, which poses unique challenges due to its heavy reliance on metaprogramming. I've provided insights into how to efficiently apply type definitions throughout the codebase and validate them with Steep, which requires careful consideration.
00:09:50.750 As I wrap up, I'd like to mention some roadblocks we faced during the type checking process. One significant challenge was the need for better support for type libraries, as many common types were not yet defined in Steep. As the tool evolves, incorporating more types and structure can enhance its utility.
00:10:50.000 Through this presentation, it’s clear that while we made considerable progress, the path ahead is still filled with opportunities to refine type inference and support for core Ruby features, ultimately aiming for a more robust and expressive type checking experience.
00:12:40.000 Thank you for your attention, and I would be happy to take any questions you might have regarding Steep or the implementation of type checking in Ruby.
00:13:35.000 Q&A: Audience member asks about the decision to drop automatic type inference. The speaker explains that while they initially aimed for automatic inference as seen in other languages, practicality and the differences in Ruby’s dynamic environment led them to favor explicit type declarations.
00:14:18.620 The speaker emphasizes the importance of explicit types to ensure correctness and programmer awareness, valuing the balanced approach of user-defined type annotations combined with the strengths of the type system.
Explore all talks recorded at RubyKaigi 2018
+62