6 ms·
Gradual type checking for Ruby
- Mithaldu 11y ago> This gem brings you advantage of type without changing existing code's behavior. I'm fairly sure it changes the performance characteristics of code it is applied on. I'd recommend adding benchmarks to the README so prospective users might be aware of this beforehand.
- overload119 11y agoThis.
- vidarh 11y agoAs someone working on a Ruby AOT compiler (whether it'll ever be finished is another matter...), I'd love to get some spec'ed out extensions for things like this with semantics that explicitly allows implementations to recognise the extension and decide to ignore the default implementation and instead provide it's own version that could e.g. do compile time checks instead of runtime checks, or hoist checks, whenever possible. Or use it for optimisations (e.g. by hoisting out and eliminating other checks and caching method lookups) Ruby is flexible enough to allow quite a bit of experimentation with stuff like that. Especially because classes can be re-opened, so if worried about performance, it'd be easy enough to allow type annotations (or whatever other extensions people come up with) to live in separate files if people want them to, and conditionally include them only as needed/wanted.
- curryhoward 11y agoWhen most practitioners think of "typechecking", they typically think about proving properties about programs statically. This project seems equivalent to adding a runtime check at each call site to ensure the arguments and return values are the correct type. This is certainly useful sometimes, as it gives programs the desirable "fail fast" property. But it isn't "typechecking" as most engineers understand it. Or at least, it should be clarified that this is run-time typechecking. As such, it negatively impacts runtime performance, unlike compile-time typechecking. This project also seems to miss the primary opportunity of run-time type checking: checking properties that are difficult to prove statically! For example, checking that a number is even, that a string is lowercase, that an index is within the bounds of an array, etc. These exotic types require a dependent type system to be checked statically, but in a dynamic environment they are trivial to verify. Two suggestions for improvement: 1) add "sum" types (i.e., discriminated unions), and 2) let the user define their own types via lambdas, such as PrimeNumber.
- girvo 11y ago> When most practitioners think of "typechecking", they typically think about proving properties about programs statically. This project seems equivalent to adding a runtime check at each call site to ensure the arguments and return values are the correct type. It basically seems equivalent (albeit somewhat nicer in a few ways, ie. scalar types are supported) to PHP's "type hinting"[0]. I will say that it is useful, in combination with unit testing, as you can pick up on problems with things slightly easier than hoping for the best in production and tailing error logs, but proper static type analysis is more useful. [0] http://php.net/manual/en/language.oop5.typehinting.php http://php.net/manual/en/language.oop5.typehinting.php
- foolfoolz 11y agoeditor support for php type hinting and phpdoc method comments goes a long way. intellij can do significant refactors and and searching. you'll get real time feedback for violating types. it's not quite the same as a explicit compile step but pretty close
- girvo 11y agoKomodo IDE helps with that, but I personally switched to HHVM and have a simple bash script that swaps the `<?php` for `<?hh` and back, so that `hh_client` can statically tell me about problems, even when I'm not using any of the Hack features. Works a treat, to be honest!
- seanmcdirmid 11y agoThis is kind of pedantic. What programmers think of and find useful as types and type systems is quite different from what type theorists think.
- nahiluhmot 11y agoI would definitely find what curryhoward described as useful, but I don't think Ruby is that language in which it should) be implemented. That being said, sum types would be a nice addition to this library.
- JoelMcCracken 11y agoThis is very similar to contracts.ruby, which is cool. I'd love for more contract discussions. https://github.com/egonSchiele/contracts.ruby https://github.com/egonSchiele/contracts.ruby
- MrDosu 11y agoPersonally I don't get contracts when they aren't used for static verification. It's much easier to use defensive coding techniques at runtime without having yet another framework in there that anyone who wants to read the code has to learn. Typing a few lines less is not really a benefit when it basically increases code complexity.
- actsasbuffoon 11y agoThe Contracts gem is very easy to use. I introduced it at work recently, and everyone got the hang of it in about 20 minutes. A lot of languages (Java, C#, Go, etc.) have very inexpressive type systems, and that tends to make many dynamic language developers wary of them. Contracts has a very expressive type system though. It understands duck typing, adhoc union types, and a bunch of other stuff that makes it a great fit for a dynamic language. Plus, we've disabled it in production, so we get coverage in test/development mode, but no performance penalty in prod. I look at it as an extended form of testing. Type contracts are very quick and easy to add, and they help tests catch additional errors. They're also useful in code reviews. Sometimes I'll have to search for 5 or 10 minutes to figure out what kind of thing is getting passed in, where the contract makes it perfectly clear. The best part is that the contracts are optional. If some method takes wildly differing arguments and it's going to be a pain to give it a contract, then don't. This is the best tool I've added to my Ruby arsenal in some time. I strongly recommend taking it for a spin.
- MrDosu 11y agoI think you misunderstood me. What I meant was that contracts in a language like C# give me the ability to statically verify the program at compile time. It is not a "nicer way to add conditional testing logic" but a way to formally prove correctness in my programs.
- shitlord 11y agoIs there an error in the section named "Typed method can coexist with non-typed method"? There's a line that has `typesig :sum` but sum is never defined.
- overload119 11y agoI've been writing Ruby for a few years on a number of production applications. Recently I've had to pickup Hack for work, and if there's one thing I really like about it is the type hinting. The best part is that it helps you handle nullable types (not sure if it's done here). When I switch back to Ruby from Hack, I find it harder to reason about my program.
- cookrn 11y agoI wonder if it would be possible to configure this gem with "environments" in the same way that Rails applications have environments. Then, in development/test/CI-like environments, very strict checking could be applied based on the specified types. Otherwise, in production-like environments where "performance" may be more important, the type-checking could be looser or simply pass-through. Disclosure: this may be a Bad Idea (TM)
- anaolykarpov 11y agoI find that putting the method signature at the end of the method definition can become unreadable pretty fast. Also, the fact that it doesn't offer any performance improvement (most probably, this will actually degrade performance) makes me see this as a cool trick, but not really recommended in production. I like the aproach Perl 6 took on gradual typing. You can read about it in this article which computes fibonnaci's number:http://blogs.perl.org/users/ovid/2015/02/avoid-a-common-software-bug-by-using-perl-6.html http://blogs.perl.org/users/ovid/2015/02/avoid-a-common-soft... The only reason I wait for the next winter to come is because Perl6 will be production ready by then as Larry Wall announced at FOSDEM this year.
- arnvald 11y agoSince Ruby 2.1 (IIRC), method definition returns symbol, therefore it's possible to something like typesig def meth(arg) arg end, [Numeric] => Numeric Although it's still end of the method, it already suggests that signature will be there
- nahiluhmot 11y agoReally cool idea! I like that you can specify a `#respond_to?` constraint instead of a class. Not sure if OP is the author, but here's some feedback: * It would be better if this didn't pollute the global namespace by defining `#typesig` in `Module` [0] -- perhaps consider refactoring that method into a module which the user may extend. Doing so would also get you out of needing to define `Module#prepend` for older versions of Ruby. * Perhaps allow the user to enable/disable type checking at a global/class level. For example, then users could only enable type checking during specs if they wanted. * Instead of using class-level variables, try using class level instance variables. They have less odd behavior when dealing with subclasses [1]. [0] https://github.com/gogotanaka/Rubype/blob/develop/lib/rubype.rb#L18 https://github.com/gogotanaka/Rubype/blob/develop/lib/rubype... [1] http://www.sitepoint.com/class-variables-a-ruby-gotcha/ http://www.sitepoint.com/class-variables-a-ruby-gotcha/ Edit: Whitespace
- saraid216 11y ago> Not sure if OP is the author The OP is eduardordm, which can be found right underneath the article link. If you look on his HN profile, his GitHub name is also eduardordm. The repo author is gogotanaka. So, no. He's not. And the repo author is consequently unlikely to ever see your comments. Not only are these simple checks to make, but it's extremely bad practice to scatter commentary about a project everywhere across the internet; people who only know about this project through GitHub would not see your comments either.
- jrochkind1 11y agoWhat are you suggesting, that there never be any discussion of code that lives in a github repo on HN, but instead all discussion take place... in the GH issues?
- saraid216 11y agoYes.
- riffraff 11y ago
- revskill 11y agoWhy Ruby 2.0 ?
- damncabbage 11y agoIn case the question is actually "Why not 1.9.3?", it's likely because 1.9.3 is End Of Life, and doesn't even get security upgrades now: https://www.ruby-lang.org/en/news/2014/01/10/ruby-1-9-3-will-end-on-2015/ https://www.ruby-lang.org/en/news/2014/01/10/ruby-1-9-3-will... https://www.ruby-lang.org/en/news/2015/02/23/support-for-ruby-1-9-3-has-ended/ https://www.ruby-lang.org/en/news/2015/02/23/support-for-rub...
- jaggederest 11y agoReminds me of https://github.com/lucky/pedant https://github.com/lucky/pedant from a few years ago. I added some basic argument assertions to it as well: https://github.com/lucky/pedant/pull/1 https://github.com/lucky/pedant/pull/1
- siscia 11y agoAny now and then another language get some sort of type check, why we don't build an agnostic type checker ? Then we interface with the AST of any language and we can stop re-iventing the wheel every two week... It is so crazy ? Nobody tried it before ?
- vinceguidry 11y agoType checking is typically done statically, i.e. during compile time. By the time you have AST it's too late. Think about it, how would you handle type annotations in an agnostic type checker?
- siscia 11y agoIt's definitely me being to naive, however I would type all the expression, in either the source code (into comment) or in a separate file, and all the statement. Now I do have a table of symbols and their type. At this point its just a matter of using the AST to being sure that everything is correctly typed... Am I wrong ?
- firlefans 11y agoMore interesting to my mind is this (Diamondback Ruby): http://www.cs.umd.edu/projects/PL/druby/ http://www.cs.umd.edu/projects/PL/druby/ Some features: -------------- Type inference: DRuby uses inference to model most of Ruby’s idioms as precisely as possible without any need for programmer intervention. Type annotations: Methods may be given explicit type annotations with an easy to use syntax inspired by RDoc. Dynamic checking: When necessary, methods can be type checked at runtime, using contracts to isolate and properly blame any errant code, similar to gradual typing. Metaprogramming support: DRuby includes a combined static and dynamic analysis to precisely model dynamic meta-programming constructs, such as eval and method_missing.
- stewbrew 11y agoIMHO the state of static type checking/code analysis in ruby is still deplorable and this (well known, rather trivial) approach won't ameliorate the situation. Even javascript has more to offer in this respect. Who would have suspected that 5 years ago. Since I still like ruby's syntax, my hopes are that crystal (http://crystal-lang.org/ http://crystal-lang.org/) will one day become more mainstream (and maybe be adapted to some extent in mainstream ruby).
- moe 11y agoThis already exists in a relatively mature form: https://github.com/egonSchiele/contracts.ruby https://github.com/egonSchiele/contracts.ruby
- transfire 11y agoAlready done many years ago: https://github.com/rubyworks/platypus https://github.com/rubyworks/platypus