18 ms·
RBS, Ruby’s new type signature language
- azinman2 6y agoInteresting. I’m surprised they didn’t opt to do this inline with the rest of the ruby code, because now they can diverge from each other. It’s a bit like a separate header file in C/C++/Obj-C, except in those cases the compiler will yell at you if the implementation doesn’t match the header. Having it blow up at runtime instead doesn’t feel like such a big change from the way it is now, other than helping out IDEs.
- CarelessExpert 6y ago> I’m surprised they didn’t opt to do this inline with the rest of the ruby code, As they mention in the post, they followed typescript's approach, here. The benefit is it allows you to layer in typing into an existing codebase in a non-disruptive way.
- azinman2 6y agoBut as I mentioned the downside of this is that any mistakes don't become evident until at runtime. While the python way has the same problem (they're not compiled languages after all), by inlining to the existing source there's less changes for divergence to happen.
- ativzzz 6y agoRemember this is designed by companies that already have existing, large, ruby codebases. For them, it makes a lot of sense to be able to incrementally add typing without having to make changes to the underlying code itself.
- joshuamorton 6y agoYou can do both. Python allows for external .pyi files, for situations where you can't modify the underlying library (for example: it's written in C). There are tons of them: https://github.com/python/typeshed https://github.com/python/typeshed, but you can still add types to new code inline.
- ativzzz 6y agoYou can, but clearly the people designing this system have weighed the pros and cons and found that there would be more benefits to them to leave the source code unchanged.
- baweaver 6y agoYeah, there was a ton of discussion on this in the Ruby bugtracker and at core meetings. Matz is very sensitive to breaking the language with Ruby 3 and the core team is doing their best to ensure an easy transition.
- mekster 6y agoSo, why would a company with different use case than average ruby users implement stuff in the core to confuse many ruby users?
- mekster 6y agoThat use case is not for most of us yet the way those companies with large code base goes into the core? I guess ruby itself already has a large code base, so it seems they got aligned but they forgot to align with the rest of the world.
- punnerud 6y agoYou can run Python type check before runtime at the cost of start time, or better before GIT commit or push (Git Hooks)
- Lio 6y agoInline types are available as a feature of the Sorbet type checker.
- untog 6y ago> As they mention in the post, they followed typescript's approach, here. They didn't, though! That's what's confusing me. TypeScript has inline types. .d.ts files are typically for JavaScript files that don't have types embedded.
- CarelessExpert 6y ago> They didn't, though! That's what's confusing me. Sure they did. It's the 5th paragraph in the post: "We defined a new language called RBS for type signatures for Ruby 3. The signatures are written in .rbs files which is different from Ruby code. You can consider the .rbs files are similar to .d.ts files in TypeScript or .h files in C/C++/ObjC. The benefit of having different files is it doesn't require changing Ruby code to start type checking. You can opt-in type checking safely without changing any part of your workflow."
- untog 6y agoThey've described part of TypeScript's approach. .rbs files: have types .rb files: no types .d.ts files: have types .ts files: have types It's a pretty significant difference. So they didn't "follow typescript's approach" here.
- floatboth 6y agoWell, .rb types won't have the standard type signatures (that could be consumed by various typecheckers) but could still have a particular typechecker's custom annotations…
- tdeck 6y agoBut that's not really TypeScript's main approach, is it? When I think of TypeScript I think of the inline colon annotations, not the external files. Those are just a bridge for legacy code.
- cschep 6y agoAfter reading the article I'm not sure, but.. it seems reasonable to assume that you can do both. Inline and separate files. The same way TypeScript does it. Hopefully, anyway!
- mekster 6y agoSorbet's FAQ seems to say otherwise. https://sorbet.org/docs/faq#when-ruby-3-gets-types-what-will-the-migration-plan-look-like https://sorbet.org/docs/faq#when-ruby-3-gets-types-what-will... > Ruby 3 has no plans to change Ruby’s syntax. To have type annotations for methods live in the same place as the method definition, the only option will be to continue using Sorbet’s method signatures.
- recursivedoubts 6y agoCool. And glad to see this called out: Better IDE integration: Parsing RBS files gives IDEs better understanding of the Ruby code. Method name completions run faster. On-the-fly error reporting detects more problems. Refactoring can be more reliable! IDE support (autocomplete, refactoring and quick documentation) is the most important reason to annotate argument and return types.
- bytematic 6y agoI've been using typescript for a few years now and to be honest I almost never rely on the compilation errors. I just use the built in Jetbrains IDE completion, autosuggestion, and navigation to make it work.
- recursivedoubts 6y agoYep. A good IDE to a first approximation doesn't allow compilation errors to occur because you are auto-completing everything, including symbol completion based on the type at cursor, etc. Jetbrains is a wonderful company.
- smabie 6y agoSince the advent of LSP, I think the value proposition of a full featured IDE has been greatly diminished. For example, I used to use Intellij for Scala but recently switched to Emacs+Metals and haven't really missed anything. In fact, it's probably an even better editing experience. Intellij still has better refactoring (though I don't use it much), and the integrated debugger and database viewer are really nice. I've found myself using Emacs and only switching to Intellij for the aforementioned specialized tasks. 5 years ago you would have been crazy not using an IDE for JVM work but this is no longer the case. LSP is such a wonderful technology and has empowered the creation of new programming languages like never before. It's truly remarkable. If I was Intellij, I would be a little worried about my future market share. They simply can't provide the same value as before, and I'm not sure how they intend to change that.
- davidkellis 6y agoAt some point it makes more sense to switch to Crystal.
- mrkurt 6y agoCrystal is amazing (we sponsor it at Fly.io), but the sheer amount of stuff that's already built for Ruby makes it hard to switch to another language. Node has had 10 years and its still not there.
- rch 6y ago> still not there And never will be.
- hombre_fatal 6y agoNot sure what you're saying. What are places where Node isn't caught up to Ruby and can never catch up to Ruby? Ruby on Rails seems like a kneejerk response, but then again it doesn't exist because nobody really wants it, not for technical reasons. For example, Python has all the ML/math stuff. Nothing comes to mind for Ruby.
- rch 6y agoI think the parent comment was referring to the overall market position of RoR, and I'm saying that Node isn't likely to achieve an equivalently dominant share going forward, due at least in part to the wide variety of options available.
- joelbluminator 6y agoNo one really wants it other than the guys who use Sails I guess...or is the name just a coincidence?
- simplify 6y ago> it doesn't exist because nobody really wants it. Clearly not true, as there's two separate fullstack frameworks being actively developed[0][1], not mentioning the ones in the past (sails.js, meteor.js). [0] https://github.com/blitz-js/blitz https://github.com/blitz-js/blitz [1] https://github.com/redwoodjs/redwood https://github.com/redwoodjs/redwood
- exabrial 6y agoTypes help communicate information to the next developer. They're important, use them!
- sparker72678 6y agoThis isn't just about Types, per se. Ruby has types all over. You can't write Ruby without them. This is about Static Typing and Type enforcement, in the context of a language that holds flexibility and meta-programming as high values.
- monadic2 6y agoHow does this interact with method_missing, the soul of rails? Obviously much of the rails api is defined dynamically, not statically. I could see runtime checks having some value but I’m not sure how an IDE could take advantage of this, period. I’d imagine you’d at least need to generate methods (rather than parse and route messages at runtime) to make this remotely viable. I’m not super familiar with ruby outside of my work so I’m not sure if this reliance on method_missing is more widespread than rails.
- avolcano 6y agoYou're correct in your assumption you'd need to generate methods, from my quick investigation into how Sorbet handles it - see https://github.com/chanzuckerberg/sorbet-rails https://github.com/chanzuckerberg/sorbet-rails for some details.
- avolcano 6y agoDidn't realize Square was interested in Ruby type checking, just like their competitors over at Stripe. Lots of money riding on Ruby, I guess :) It does seem useful to have a _standard_ for type definitions - RBS as the equivalent to a .d.ts file - as that allows for different type checking implementations to use the same system under the hood. This was a big problem for Flow, and why it lost the fight as soon as TypeScript's definitely-typed repository started gaining momentum - users wanted to use the type-checker that they knew had definitions for the libraries they used. On the other hand, RBS as hand-written seems rather dangerous, to me. Nothing wrong with using them to define previously-untyped external code, as long as you know the caveats, but I think you really want to have definitions generated from your code. Sorbet cleverly (and unsurprisingly, given it's Ruby) used a DSL for definitions in code, which had the (excellent) additional boost of runtime checking, so you actually could know whether your types were accurate - by far the biggest pain-point of erased-type systems like TypeScript. Given that Ruby 3 was supposed to "support type checking," I'm surprised that it does not seem to have syntax for type definitions in code, and instead will focus on external type checking. I might be missing a piece of the full puzzle not covered in the blog post, however.
- ucarion 6y agoFor other readers: "Sorbet" refers to https://sorbet.org/ https://sorbet.org/, Stripe's Ruby type checker.
- avolcano 6y agoapologies, meant to add that as a link when I referenced Stripe in the first sentence!
- shpongled 6y agoI'm not familiar with Ruby at all, but presumably it'd be possible to at least generate stubbed out definition RBS files with type inference.
- baweaver 6y ago
- hartator 6y ago> Typed languages are suitable for larger projects but are often less flexible. Untyped languages allow for rapid development, but scaling teams and codebases with them can be difficult. Well some of us disagree with the statement that untyped is not suitable for large teams. And that's why we use Ruby. There is a lot of very good typed languages out there if you do want typed. I feel Square and Stripe are pushing their own codebase issues onto general Ruby - as it's our problem to solve - which is not cool.
- muglug 6y agoCan someone explain why the types cannot live in Ruby code itself (after an appropriate version bump)? Python 3 incorporated types into the language itself, in a similar way (though non-reified) to PHP. This seems much easier to deal with than requiring two files (.rb and .rbs) to describe a single data structure.
- skywhopper 6y agoBased on the relative smoothness of Ruby version transitions versus Python, I trust Matz’s preference on this implicitly. One good thing about it being external is that you can optionally and experimentally annotate existing code without munging up your source files. At least so long as this is a bleeding edge feature, that separation makes a lot of sense to me. It’ll be a while before anyone can be confident in a particular model for how this should work, until it’s been in use for a good long while.
- baweaver 6y agoPretty much. Matz is very sensitive to breaking the language in any way with the Ruby 3 upgrade, which brought up the true keyword argument hard-break and [likely got that pushed back](https://discuss.rubyonrails.org/t/new-2-7-3-0-keyword-argument-pain-point/74980 https://discuss.rubyonrails.org/t/new-2-7-3-0-keyword-argume...). RBS and type files on the side were really hotly debated for a while and the core team settled on this as a way to not break the existing parser among other reasons. While I don't 100% agree with them I have faith that Matz and the team make the decisions they do based on impact and what they see in the community.
- Jabbles 6y agoHis view is probably informed by the Python 2->3 experience.
- baweaver 6y agoIt was, and I was around during one of his discussions on that at RubyConf last year. It's a very valid concern and Matz is very sensitive to it. There are a lot of things he's joked about removing or changing but won't because of those reasons. If you take a look at his keynote video he says quite a bit on this too.
- danfritz 6y agoHow does this compare to the sorbet project? Is it two different implementations for the same goal or is it adding support in ruby so sorbet can also benefit?
- zrail 6y agoThe sorbet project has an FAQ about that (I was curious too): https://sorbet.org/docs/faq https://sorbet.org/docs/faq search for “RBS” (on mobile, no deep links)
- ghiculescu 6y agohttps://sorbet.org/docs/faq#when-ruby-3-gets-types-what-will-the-migration-plan-look-like https://sorbet.org/docs/faq#when-ruby-3-gets-types-what-will...
- riffraff 6y agoAFAIU sorbet can consume RBS files, and probably produce them from libraries that use it. But other type checkers could be implemented relying on the same information.
- baweaver 6y agoThat's correct. Sorbet currently uses RBI but after meeting with core they standardized on RBS and are migrating to present a more unified front and enable easier development of type checking libraries on top of it. Very little of this will need to be written by hand. The underlying tech is pretty decent at guessing types, the idea is that if it's not quite specific enough you adjust it, but it should otherwise be transparent.
- darkdimius 6y ago(One of core devs on Sorbet) Agreed. But don't read too much in RBS details yet. RBI is currently very early and will need to change substantially learning from experience of actually typechecking real codebases. Stripe and Shopify are helping with this. RBS has better syntax, but has features that don't have clear semantics or feasible implementation. And doesn't support inline annotations that are necessary in practice. RBI is limited by ruby syntax and thus isn't as nice, but has good semantics and support inline annotations. And has been tried on hundreds of real codebases including those with dozens of millions lines of code. We'll need to gather benefits of both on our way forward.
- ch_123 6y ago> Typed versus untyped is a 30-year-old issue for programming languages. I'm pretty sure the merits of typed vs untyped has been going on since the 1950s at least. 30 years is such a specific period of time that it makes me wonder what happened in the early 90s that the author is referring to.
- cschep 6y agoRuby was invented? :)
- HideousKojima 6y agoAnd JavaScript and Python, and a whole host of languages that didn't care about strong typing
- ch_123 6y agoNone of these were the first untyped languages, or even the first widely used untyped languages.
- vidarh 6y agoIn fact none of them are "untyped". They are strongly typed. BCPL could conceivably be described as untyped.
- vidarh 6y agoRuby and Python are both strongly typed. They are not statically typed.
- yakshaving_jgt 6y agoRuby is only 25, but Haskell is 30.
- bastardoperator 6y agoNope, that happened 5 years later.
- didip 6y agoIt has been so long since I last heard activities on Ruby. I had assume people moved on to Go or Rust for high traffic work by now.
- Falling3 6y agoSounds like selection bias.
- ativzzz 6y ago> for high traffic work Considering how prevalent Rails is for Ruby, we can assume that the majority of Ruby codebases are web apps. There are tons of way to scale Ruby web apps for high traffic, and a tiny minority of companies end up reaching a scale (like Twitter) where Ruby becomes infeasible.
- pupdogg 6y agoHow long has that been? Since Square, Stripe and Shopify closed their shop?
- Lammy 6y agoIt’s a separate RBS file for now, but if/when this gets integrated into Ruby itself how will it interact with the new Ruby 2.7/3.0 keyword argument syntax that also uses the colon? https://bugs.ruby-lang.org/issues/14183 https://bugs.ruby-lang.org/issues/14183
- rattray 6y agoDifficult questions like that are exactly why matz refused to integrate this into .rb file syntax!
- jrochkind1 6y agonote that syntax isn't actually new in ruby 2.7 or 3.0 at all. It's been around since ruby 2.0 in fact (Feb 2013). (keyword arguments had to be declared with default values until ruby 2.1, Dec 2013). What ruby 2.7/3.0 do is rationalize some really weird counter-intuitive and ambiguous edge cases related to passing a Hash arg expecting it to be invoked as if it were keyword args. But it's a change in semantics, not syntax. The keyword argument syntax, keyword arguments with colons, in both method definitions and invocations, has been around for years, unchanged.
- stewbrew 6y agoSeparate ruby header files with type information? Seriously? What's the rational behind that? Is it just to make clear that the ruby interpreter doesn't really care about the type information and doesn't use it to improve the code's performance? With all due respect, but IMHO this is too little and much too late.
- learc83 6y ago"The benefit of having different files is it doesn't require changing Ruby code to start type checking. You can opt-in type checking safely without changing any part of your workflow."
- HideousKojima 6y agoTypeScript allows this while also allowing inline type declarations, without breaking existing JavaScript
- hombre_fatal 6y agoBut it's not Javascript anymore. Seems reasonable for someone to want types but not have to raise their own entire TypeRuby language + ecosystem + re-tooling.
- saghm 6y agoIsn't this similar to how TypeScript allows annotations for JavaScript to live in separate files? My (possibly naive) assumption is that the goal is to make it easier for developers to write type annotations for projects they use without necessarily having to convince the maintainers to add them to the project itself. I've heard of people using TypeScript annotations from https://definitelytyped.org/ https://definitelytyped.org/ for dependencies which don't have their own annotations.
- TomMarius 6y ago.d.ts files are mostly compilation output, only if the original source is JavaScript you write the definitions by hand. TypeScript developers normally work with types inside their ordinary .ts (JS+types) module file, not in a separate source file.
- welearnednothng 6y agoIt's worth noting that while the article is coming from Square, this is an official Ruby project and is "Ruby 3’s new language for type signatures". https://github.com/ruby/rbs https://github.com/ruby/rbs
- baweaver 6y agoThis. RBS is the underlying language for defining type checkers. Sorbet and Steep both utilize it, and this allows future type checkers to evolve from a known-base instead of having to reinvent everything.
- rattray 6y agoYeah, I was wondering why this was being announced on Square's website. Seems it's because Square happens to employ Soutaro Matsumoto, who wrote the post and is also the creator of Steep[0] (an implementation of a typechecker for RBS files). It's not clear to me whether Soutaro is a member of the Ruby core team, so it feels a bit odd that the post is written like an announcement from the Ruby maintainers. [0] https://github.com/soutaro/steep https://github.com/soutaro/steep
- baweaver 6y agoSoutaro is indeed a code member of the Ruby team, he also happens to work at Square. Soutaro is also one of the main contributors to RBS and helped define that standard. He was going to keynote on this at RubyKaigi this year until it was cancelled, and had a talk at RubyConf as well on this.
- rattray 6y agoThanks for clarifying! It's great that Square is funding work like this.
- baweaver 6y agoYep, and glad to see the work Stripe is doing on things as well. Always enjoy seeing where you all are going. Soutaro has been great to work with over here (Square), and he has a ton of really amazing things coming soon that we're working on OSS'ing later.
- freedomben 6y agoI'm not thrilled about the separate files with the type information but I completely understand why they did it, and if it were my choice I might make the same one. I don't like the comparison with TypeScript `.d.ts` files however, because TS still lets you do types inline in the code. I haven't seen it mentioned anywhere that this won't be supported by Ruby 3. Does anybody know if Ruby 3 will also support inline type information or will the header RBS files be required?
- amw-zero 6y agoI much prefer separate files for type declarations. Or at least the ability to define them separately. Type annotation takes away from readability. I like keeping the types and code separate.
- hombre_fatal 6y agoThe upside of external files is pure incremental implementation that touches no other tooling and requires no buy-in. I don't see how having to switch files to know that `input` is a `User` increases readability, though. It seems like straight-forward impl-simplicity trade-off, not one of user ergonomics.
- strogonoff 6y agoSeparating type definitions from code can be considered as contributing to readability of idiomatic Ruby on one hand, and type definitions on the other, taken separately on their own—by not imposing constraints on either syntax. IDEs will likely be able to seamlessly peek/go to RBS type definition on any Ruby identifier in any case.
- mekster 6y agoThat can be covered by the editor to give the user some hint by referencing the external file but for the user, having have to keep adding it on a separate file seems pretty annoying as you need to keep declarations synched in 2 files. Also how do you type something in an inline function?
- alexpapworth 6y agoReally exciting!
- hirundo 6y agoAnyone know, or have a guess, what RBS stands for? I'm not finding it in the article or library.
- loktarogar 6y ago.rb is a ruby file, so it's more what the s stands for
- haven 6y agoSignature. The Ruby::RBS library used to be called Ruby::Signature.
- allknowingfrog 6y agoI'm seeing the type annotations being referred to as "signatures" in a couple of places. (R)u(B)y (S)ignatures seems like a reasonable guess.
- baweaver 6y agoThat would be correct.
- satisfaction 6y agoI wonder if this type information can be used by the vm to improve performance?
- baweaver 6y agoMatz had mentioned this as a key reason he was interested in working on this, as well as a "language server" with a lot of really interesting features like what JS/TS has with VS Code. I had the good fortune to hear him talk about it at length at a conference a while ago and there's all types of fun stuff on the way.
- burke 6y agoI absolutely hate this. Separate files for types with no inline annotations possible? What an embarrassing compromise. This is all because Matz explicitly won't allow type signatures in .rb files. I wonder how long it'll be until a hostile fork if he doesn't change his mind.
- amw-zero 6y agoI wouldn’t call it “embarrassing.” What is the actual benefit of having inline type annotations? What is the actual downside of having them in a separate file?
- burke 6y agoIf we're going to add type signatures to code, having them visible alongside their definition site is a sizeable part of the value; and, littering directories with doubled files feels suboptimal to say the least. The comparison to typescript in the article isn't really fair, since typescript supports both modes of operation - projects can choose which they'd like to use.
- HideousKojima 6y agoThe benefit is being able to see what type a variable is without having to open a separate file. Having an option to also have them in a separate file (ala TypeScript) is perfectly fine
- yawaramin 6y agoType info on hover in your editor gives you that.
- mekster 6y agoHow hard is it to imagine that you need to keep 2 files in sync, and that you can't type anything inside a method. I was even hoping to use ruby as a main language having used it before but I'm about to lose any interest in the language when its reality is a bit decoupled from the rest of the world.
- setpatchaddress 6y agoI'm really puzzled by the decision to use a separate file for this. The stated justification ("it doesn't require changing Ruby code") doesn't make sense, and my personal experience with languages with external type specifications is strongly negative. It's an unbelievable pain to keep multiple interface files in sync over time. `.h` files are not something to emulate! External interfaces should be generated by tools where needed.
- michaelfeathers 6y agoSeparate files make sense if you consider typing a form of coupling. I pitched the idea for something like RBS in Ruby back in 2006. The reasoning is here: https://www.artima.com/forums/flat.jsp?forum=106&thread=155960 https://www.artima.com/forums/flat.jsp?forum=106&thread=1559...
- fasterpython 6y agoYeah I agree with this. They cite the typescript compiler, which in addition to supporting .d.ts files also supports compiling regular JS in additon to separate TS files in the same project. I think this would have been a better approach for backward compat as well, so that users could upgrade to versions szupporting static typing and incrementally change projects one file at a time (leaving existing code intact).
- heavenlyblue 6y agoHow do you even type local variables?
- RangerScience 6y agoWhy would you need to? Edit: Like, seriously. Either the local var is populated by something coming in externally (which is then typable) or, unless your code is too complex / large, it should be easy to see everywhere it's used, and then why would you need that additional typing info?
- viraptor 6y ago
- AaronFriel 6y agoI likely am missing some context, but the comparison to TypeScript's ".d.ts" files seems misplaced. This is a type signature language, but it does not seem to be a type checker. The comparison to .d.ts files then seems bizarre because that is helpful for language servers¹ to consume types, but there's no proof that say, the implementation matches the type specification. TypeScript declaration files declare what the types of module exports are. For the most part, a .d.ts file informs the typechecker "the type of module Foo export bar is the interface named Quux". This is not checked, this is simply an assertion. The language server for TypeScript will pick these definitions up, assume they are correct, and provide code completions for those types as if they were correct. On the other hand, a .ts file, combining types and codes, enables type checking. If the type declarations are incompatible with the code, an error is thrown by TypeScript. While .d.ts files declare types, .ts files verify that the code and the types declare are compatible. Since .rbs files simply describe the external interface of types and modules, and cannot describe internal variables, I'm not sure how it's doing any type checking. For example, if I have this code: module Foo class Bar def trivial: () -> String end end What prevents me from writing this: class Bar def trivial return 42 end end Or alternatively, this: class Bar def trivial x = some_function_that_might_not_be_declared_in_an_rbs_file() return x end end Does x have a type? Can I gradually type "class Bar" via type inference, or do I have to declare and keep in sync all my rbs files with my rb files? What happens when the rbs file is out of sync with the rb file? ¹ Language servers are implementations of an IDE protocol for code completion. The trend in programming language tooling is to use Microsoft's Language Server Protocol (https://microsoft.github.io/language-server-protocol/ https://microsoft.github.io/language-server-protocol/) to provide code completion, semantic navigation, refactoring, etc.
- rattray 6y agoThe type checker implementations (eg; Steep, Sorbet) should throw an error at `return 42`. If `some_function_that_might_not_be_declared_in_an_rbs_file` is not known, the behavior may be configurable – it could be assumed to be something like `any` or assumed to be unsafe, and error until you declare that function. I think Sorbet has this configurability today, and I'm not sure about Steep's behavior. Steep: https://github.com/soutaro/steep https://github.com/soutaro/steep Sorbet: https://sorbet.org https://sorbet.org
- bytematic 6y agoI just want typescript for ruby. That simple
- mekster 6y agoWith all the prior arts, I'm not sure how ruby didn't pick up the good parts and made it better than others.
- swagonomixxx 6y agoI haven't used Ruby in ages but this seems like a really odd way to incorporate type hints in the language. I much prefer the Python 3+ approach of type annotations in source code. I can't imagine having to look at a separate file just to figure out what the type of something is. You may say "tooling will fix this" but it's just far less overhead for everyone at the end of the day to just make annotations in source. My more existential question is, is there really an advantage to doing static type checking in Ruby? When I was doing Ruby, the way you can change objects on the fly, add methods on the fly, the vast amounts of metaprogramming, are types at "compile" (I know, not really) time really the same as types at runtime? Like, it might be nice to get some autocomplete, but AFAIK tools already do that (RubyMine, others).
- miohtama 6y agoYou might be correct. There have been attempts to have types outside the main source or in comments for many dynamically typed languages. They seem to fail due bad programming ergonomics, as maintaining separate "header" files is cumbersome (hello C my old friend).
- 3pt14159 6y agoThis is why I do not like mypy or types in Python other than dataclasses. If I'm going to type the damn thing I better be getting performance ala cython. Why on earth use a dynamic language like Ruby or Python and then try to bolt types on top. Ruby would do far better to fix the bloody `and` vs `&&` issue (it should just be `and` and it should work like `&&`) and strings should be immutable by default with a special syntax or method to make them immutable. But you're absolutely right about the downsides of stuffing types into a different file. I get why Matz did it (he wants to keep Ruby beautiful and types are crufty) but I don't like them in the first place.
- julvo 6y ago> Why on earth use a dynamic language like Ruby or Python and then try to bolt types on top Probably using the languages for the ecosystem (e.g. Python for scientific computing or ML and ruby for ruby on rails) but still wanting to benefit from type checking
- vidarh 6y agoThe article's use of "typed vs untypes" instead of "statically vs dynamically typed" is really unfortunate, and doesn't exactly inspire confidence.
- _nalply 6y agoYou mean because the word "untype" is a negation and as such doesn't evoke a positive tune?
- vidarh 6y agoNo, because it is wrong. Ruby is not untyped. It is dynamically and strongly typed. BCPL is an untyped language. One of very few.
- MaxBarraclough 6y agoIndeed. To expand on your point: yep, it's incorrect. An untyped language is a language in which there is no concept of type. Assembly languages tend to be untyped. Forth is untyped. The Ruby and Python languages do have the concept of type, it's just that they're dynamically typed, not statically typed. They check types at runtime.
- iso8859-1 6y agoBut when you have things like "duck typing", don't you think "they check types at runtime" becomes less meaningful? The majority of functions written in Python, even the ones that have type annotations, do not effectively have "assert isinstance(...)" in the program text below their signature, which is what I'd expect after reading "check types at runtime". Also, Python now has (in its stdlib!) things like typing.Protocol, which is almost exclusively checked at type checking time. So if such a thing exists, and you still say "types are checked at runtime", isn't that confusing?
- vidarh 6y agoI don't really know what you're trying to say here. Why would it be less meaningful to say types are checked at runtime with ducktyping? The nature of ducktyping is that the specific class of an object does not matter relative to behaviour, but a class is not entirely equivalent to a type. If I need an object that implements method `foo`, and don't care about class, then "objects that implements foo" is in itself a type, that can potentially be inferred and checked be it at runtime or before. > The majority of functions written in Python, even the ones that have type annotations, do not effectively have "assert isinstance(...)" in the program text below their signature, which is what I'd expect after reading "check types at runtime". You're thinking his "checks types" too narrowly. Every time I try to call a method on an object in a strongly typed language, typing is involved. It doesn't so much "check" it as look up the method to see whether this method applies to this specific object at this point in time and decide whether or not to throw exceptions. But the point remains that it is a typed. And strongly so - in both Ruby and Python objects has a type associated with the object itself, unlike e.g. C or C++ which are weakly typed because it is the variables that are typed, not the values.
- phjesusthatguy3 6y agoRBSup dawg. I heard you like type signatures, so I created a file format called .rbs, so you can alt-tab while you code.
- mekster 6y agoMore like ctrl-tab in the same editor.
- RangerScience 6y agoI'm really loving how this is intended as a starting point, so that the community can continue to build and explore on top of it. Feels very Ruby Is Nice, So We Are Nice.
- cheez 6y agoI prefer Python's typing module to this.
- historyremade 6y agoRBS Bank going to sue you bitch.
- dzonga 6y agobest type-checking system in my experience has been F#. You don't even have to declare types.
- vemv 6y agoChecking that something is a String is pretty weak and uninteresting. How about checking that a given string is non-blank? That tends to fully leverage Ruby's dynamic nature. But then again people are overly fixated with compile-time, Java-like signatures. See clojure.spec for a success story.
- sixstringtheory 6y ago> How about checking that a given string is non-blank? Because when you try to do this with some object that doesn't have a "length" or "empty?" method, your application crashes. irb(main):013:0> a = 1 => 1 irb(main):014:0> b = "1" => "1" irb(main):015:0> b.length => 1 irb(main):016:0> a.length Traceback (most recent call last): 4: from /usr/bin/irb:23:in `<main>' 3: from /usr/bin/irb:23:in `load' 2: from /Library/Ruby/Gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>' 1: from (irb):16 NoMethodError (undefined method `length' for 1:Integer) irb(main):017:0> b.empty? => false irb(main):018:0> a.empty? Traceback (most recent call last): 4: from /usr/bin/irb:23:in `<main>' 3: from /usr/bin/irb:23:in `load' 2: from /Library/Ruby/Gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>' 1: from (irb):18 NoMethodError (undefined method `empty?' for 1:Integer) This is why people want a way to know if something they think is a String is actually a String, without risking data loss and outages at runtime. I think it's rude to dismiss people asking for this as "fixated," and furthermore it could be no less fairly used against people who show up to these debates beating their own drum against it.
- vemv 6y agoOne can check that something is a string and not a blank one. There are two different libraries that do it: https://github.com/plumatic/schema/blob/ddb54c87dea6926c6d73542e517b53685cc82a37/src/cljx/schema/core.cljx#L594 https://github.com/plumatic/schema/blob/ddb54c87dea6926c6d73... https://github.com/clojure/spec.alpha/blob/eb49d429e85b6878a61443e853be26092ff6e249/src/main/clojure/clojure/spec/alpha.clj#L495 https://github.com/clojure/spec.alpha/blob/eb49d429e85b6878a... Honestly I highly suspect that many, many "typing" solutions out there are plain ignorant of the whole spectrum of choices one can make, are tend to lean towards Java-like APIs out of that ignorance. This is not limited to Ruby, I also see it in TypeScript which is very much a contrived system for real-world usages while making little use of JS's dynamism.
- lovetocode 6y agoAs an avid Rubyist I have no interest in introducing types into a dynamic language. I would just rather use C# or Java. I never understood why people are trying to make a round peg fit in a square hole.
- klysm 6y agoMassive code bases that are difficult to maintain and refactor. It’s a cheaper effort to add types to that code.
- deleted 6y ago[deleted]
- matthewmacleod 6y agoRuby has types already, everywhere. An optional system that annotates these types and expresses relationships between them—allowing you to specify constraints and detect errors that you would otherwise not notice—is a win-win.
- steve_adams_86 6y agoI think of it a little differently. I'm excited. I love these incremental type systems. I don't want to write C# all the time at all, but I do find myself missing it occasionally. These systems are excellent for easing that pain when a language like C# isn't an option. When a statically typed, compiled language is an option I tend to choose Rust lately just for novelty and curiosity, but it's rare that I have those options. When I don't, I find these tools are a godsend. You don't really lose flexibility at all.
- symlinkk 6y agoIt’s insane to me that people are still arguing against static types. TypeScript has proven that you can add the safety of static types without taking away any of the flexibility of dynamic typing. Every time you dive deep into source code to figure out what a field is called or what a function expects, remember that you could have eliminated that completely with static types.
- 6y ago
- jrochkind1 6y agoI don't understand the benefits of forcing it to be in a separate file. I'd rather at least optionally you could include the types in the source file where you defining the methods. Being able to define an interface instead of pure un-specified "duck type" is great.
- castwide 6y agoI'm still trying to make sense of this announcement. With a lack of type annotation in the Ruby core, I chose to build off YARD to make gradual type safety work. Now I don't know if there will be a standard that supports type safety or if I should continue down the path I'm already following. Help me, Ruby core developers. You're my only hope. (edit: I should have explained that I'm talking about the type checking features I'm developing in Solargraph: https://solargraph.org/guides/type-checking https://solargraph.org/guides/type-checking)
- d3nj4l 6y agoPersonally, I think you should keep using YARD, because people are bound to be using Ruby <3.0 for a while. As an aside, thanks for solargraph! I can't recommend it enough.
- halostatue 6y agoPlease don’t use YARD. As a documentation format, I find it noisy. As a documentation generator, it doesn’t support standard RDoc syntax (_intentionally_ so) that makes it completely useless. I say this as someone who has written Ruby for almost twenty years. I will _never_ use a tool that depends on YARD document formatting, because I will never use YARD document formatting.
- transfire 6y agoI hear you. It occurred to me that Ruby could have chosen to innovate with something like a Semantic TomDoc. To choose a separate file based approach seems like a step backward. At the very least it could have been module based. But Matz is a C coder -- not a Ruby coder. So it doesn't necessarily surprise me. It's sad though. Since poor design of Refinements, C transpiling for 3x project, and now this, I am less and less inclined to continue using Ruby. I miss some of the dynamics but I find myself using Crystal instead. (Honestly, if any one figured out a way to supplement Crystal with dynamic behavior for those features that a static language can't offer, Ruby would be done.)
- d3nj4l 6y agoAs soon as I feel comfortable maintaining a Crystal server in production I think I'll switch to it. Last I tried it, things broke and shards required some effort to maintain every version update. I'm eagerly looking forward to their 1.0 and hoping they stabilize a lot more.
- Lio 6y agoI use unit tests as a design and documentation tool. Since we already have a specification tool (MiniTest) in the StdLib it would interesting if we could combine the rbs files with spec unit tests. I already have my matching test file open anyway. Having the typing information in the same place would encourage the use of types, tests and documentation.
- pjmlp 6y agoThey would do better contributing to Crystal, but what do I know.
- xmdx 6y agoI guess this is just the foundation. A way to check types before runtime. I can see a lot gems making this experience better so I'm not too worried about that. It will become better, and it is optional. For the time being I think this kind of type checking is only worthwhile in big projects, for smaller projects I have found Sorbet never finds an error, so it's just extra work to generate the files on a big change.
- Vanit 6y ago> Untyped languages allow for rapid development Citation needed. In my experience this is a fallacy; types take no time at all to write and significantly reduces bugs (Typescript).
- transfire 6y agoNo multimethods for you!