from Hacker News

Gradual type checking for Ruby

by eduardordm on 4/9/15, 2:10 AM with 42 comments

  • by curryhoward on 4/9/15, 2:59 AM

    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.

    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.

  • by Mithaldu on 4/9/15, 2:45 AM

    > 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.

  • by JoelMcCracken on 4/9/15, 3:18 AM

    This is very similar to contracts.ruby, which is cool. I'd love for more contract discussions.

    https://github.com/egonSchiele/contracts.ruby

  • by anaolykarpov on 4/9/15, 4:09 AM

    I 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-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.

  • by cookrn on 4/9/15, 3:51 AM

    I 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)

  • by moe on 4/9/15, 12:27 PM

    This already exists in a relatively mature form: https://github.com/egonSchiele/contracts.ruby
  • by nahiluhmot on 4/9/15, 4:16 AM

    Really 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...

    [1] http://www.sitepoint.com/class-variables-a-ruby-gotcha/

    Edit: Whitespace

  • by jaggederest on 4/9/15, 5:34 AM

    Reminds me of 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
  • by overload119 on 4/9/15, 3:39 AM

    I'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.

  • by firlefans on 4/9/15, 7:40 AM

    More interesting to my mind is this (Diamondback Ruby):

    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.

  • by siscia on 4/9/15, 6:24 AM

    Any 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 ?

  • by stewbrew on 4/9/15, 12:37 PM

    IMHO 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/) will one day become more mainstream (and maybe be adapted to some extent in mainstream ruby).

  • by transfire on 4/9/15, 1:47 PM

    Already done many years ago: https://github.com/rubyworks/platypus
  • by shitlord on 4/9/15, 3:30 AM

    Is 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.
  • by revskill on 4/9/15, 4:57 AM

    Why Ruby 2.0 ?