{"id":15491779,"url":"https://github.com/tristanpenman/ruby-type-checking","last_synced_at":"2025-03-28T16:42:43.657Z","repository":{"id":74416354,"uuid":"582292064","full_name":"tristanpenman/ruby-type-checking","owner":"tristanpenman","description":"Random experiments in Ruby Type Checking 🔬","archived":false,"fork":false,"pushed_at":"2024-03-26T21:08:54.000Z","size":33,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-19T10:23:53.621Z","etag":null,"topics":["metaprogramming","ruby","sorbet","type-checking"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tristanpenman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-12-26T11:03:54.000Z","updated_at":"2023-04-10T23:53:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"be01f661-243e-4972-8703-31c408ebf7dd","html_url":"https://github.com/tristanpenman/ruby-type-checking","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristanpenman%2Fruby-type-checking","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristanpenman%2Fruby-type-checking/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristanpenman%2Fruby-type-checking/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tristanpenman%2Fruby-type-checking/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tristanpenman","download_url":"https://codeload.github.com/tristanpenman/ruby-type-checking/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246068238,"owners_count":20718501,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["metaprogramming","ruby","sorbet","type-checking"],"created_at":"2024-10-02T07:56:20.966Z","updated_at":"2025-03-28T16:42:43.568Z","avatar_url":"https://github.com/tristanpenman.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ruby Type Checking\n\nThis repo contains some experimental code that I've written while learning about type checking in Ruby. The aim of these experiments has been to better understand Ruby, and to reason about how runtime type checking works in [Sorbet](https://sorbet.org).\n\nMy findings have been written up as a series of posts, _Roll Your Own Ruby Type Checking_, on my blog:\n* [Part 1](https://tristanpenman.com/blog/posts/2022/12/26/roll-your-own-ruby-type-checking-part-1/)\n* [Part 2](https://tristanpenman.com/blog/posts/2023/05/13/roll-your-own-ruby-type-checking-part-2/)\n* [Part 3](https://tristanpenman.com/blog/posts/2023/05/20/roll-your-own-ruby-type-checking-part-3/)\n\nThe code examples here roughly follow the structure of these posts.\n\n## Part 1 - Annotations, Hooks and Type Checking\n\nThe code for part 1 can be found in [part-1.rb](part-1.rb). This code demonstrates a technique for implementing method annotations in Ruby, allowing a method to be annotated with hooks that are run before and after the method body. This is then adapted for type-checking.\n\nThis code can be run from the command line with no arguments:\n\n    ruby part-1.rb\n\nCurrent output is expected to look like this:\n\n    Example 1:\n    test, test, test\n\n    Example 2:\n    before: [\"test\", 3], {:separator=\u003e\", \"}\n    after: test, test, test\n    test, test, test\n\n    Example 3:\n    before: [\"test\", 3], {:separator=\u003e\", \"}\n    after: test, test, test\n    test, test, test\n\n    Example 4:\n    testtesttest\n\n    Error: Invalid type for arg 1; expected: Numeric\n\n## Part 2 - Optional and Additional Parameters\n\nThe code for part 2 can be found in [part-2.rb](part-2.rb). This code addresses some of the limitations of the type checker implemented in part 1, while also making it more robust.\n\nThis code can be run from the command line with no arguments:\n\n    ruby part-2.rb\n\nThere are quite a few examples in part 2. The beginning of the output should look like this:\n\n    Example 1a:\n    [:req, :a]\n    [:opt, :b]\n    [:rest, :c]\n    [:keyreq, :d]\n    [:key, :e]\n    [:keyrest, :f]\n\n    Example 1b:\n    [:req, :a]\n    [:opt, :b]\n    [:rest, :c]\n    [:keyreq, :d]\n    [:key, :e]\n    [:keyrest, :f]\n\n    Example 2a:\n    [\"a\", 1]\n    [\"b\", 2]\n    [\"c\", [3, 4]]\n    [\"d\", 5]\n    [\"e\", 6]\n    [\"f\", {:f=\u003e7, :g=\u003e8}]\n\n    ... SNIP! ...\n\n## Part 3 - Breaking Sorbet\n\nWhile experimenting with my own type checker, I found that there were some fundamental limitations on how runtime type checking can be performed in Ruby. Specifically, it's not possible to verify the types for parameters with default arguments, when those arguments are omitted.\n\nThis has been demonstrated using Sorbet in [part-3.rb](part-3.rb). You'll need to install the `sorbet-runtime` gem to run this code.\n\nTo illustrate how this differs from Python, [part-3.py](part-3.py) has also been included. This highlights the fact that, no matter which approach you choose, you end up with surprising behaviour.\n\n## License\n\nThese examples are in the public domain.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftristanpenman%2Fruby-type-checking","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftristanpenman%2Fruby-type-checking","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftristanpenman%2Fruby-type-checking/lists"}