Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby Programming with Static Type Checking

Ruby Programming with Static Type Checking

At Fog City Ruby Meetup.


Soutaro Matsumoto

August 15, 2018


  1. Ruby Programming with Static Type Checking Soutaro Matsumoto

  2. None
  3. @soutaro on GitHub/Twitter

  4. from Tokyo, Japan

  5. CTO at Sider,
 an automated code review service

  6. Steep, Gradual Typing for Ruby

  7. –Matz (RubyKaigi 2016) “We need something similar to static type

  8. Type Checkers for Ruby • Steep: https://github.com/soutaro/steep • Sorbet: https://sorbet.run

    • RDL: https://github.com/plum-umd/rdl • mruby-meta-circular: https://github.com/miura1729/ mruby-meta-circular
  9. None
  10. What is Type Checking • A program verification based on

    type system (without executing the program) • Detect some kind of errors: NoMethodError, ArgumentError, null dereferencing, ... • You can do that with tests (but they depend on execution paths)
  11. Type Checking for Ruby • Pros • Confidence that your

    program won't raise the errors (correctness) • Cons • Sacrifice some flexibilities of Ruby programming • Extra declaration or annotation of types
  12. Type Checking Properties • Correctness: If type checking says your

    program is ok, no runtime error will be raised during execution • Flexibility: Type checker can accept more Ruby programs • Number of annotations: Ruby programmers don't want to write type annotations
  13. Designing Type Checker • Keep it as correct as possible

    • More flexibility with annotations • Declare type of classes/modules/methods explicitly • Write type annotations in Ruby code if necessary (local type inference to minimize # of annotations) • Steep follows this strategy
  14. Steep Quick Tour 1. Write type definitions 2. Write Ruby

    code 3. Write type annotations if necessary 4. Run type checker $ gem install steep https://github.com/soutaro/steep
  15. Write Type Definitions class Meetup attr_reader talks: Array<Talk> attr_reader capacity:

    Integer @all_attendees: Array<Attendee> def initialize: (capacity: Integer, talks: Array<Talk>) -> any def each_attendee: { (Attendee) -> void } -> void | -> Enumerable<Attendee, void> def <<: (Attendee) -> self def attending?: (Attendee) -> bool def spots_left?: () -> bool end
  16. Write Ruby Program class Meetup def spots_left? @attendees.size < capacity

    end def <<(attendee) raise "Meetup is full!" unless spots_left? raise "Already registered!" if attending?(attendee) @attendees << attendee self end def attending?(attendee) each_attendee.include?(attendee) end ... end
  17. Write Ruby Program def spots_left? @attendees < capacity end meetup.rb:3:4:

    NoMethodError: type=::Array<::Attendee>, method=< (@attendees < capacity)
  18. Write Type Annotations • Some Ruby code requires type annotations

    (or casts) # @type var attendees: Array<Attendee> attendees = [] attendees.push Attendee.new(...) # @type var number: Integer number = object.__send__(:to_i) # @type var number: Integer number = _ = "string"
  19. Ruby Programming with Steep • Does it support duck typing?

    • Types of gems? • Linters and editors? • Is type checking required?
  20. Duck Typing? • Object types are type checked with the

    methods and their types class Attendee def join(collection) collection << self end ... end attendee.join(Meetup.new) # OK attendee.join([]) # OK attendee.join("") # Error Any object is ok if it has << operator which accepts Attendee
  21. Duck Typing? • Meetup#<<: (Attendee) -> Meetup • Array<Attendee>#<<: (Attendee)

    -> Array<Attendee> • String#<<: (String) -> String interface _Attendable def <<: (Attendee) -> self end class Attendee def join: (_Attendable) -> void ... end
  22. Types of Gems? • Some gems will ship with their

    type definitions • I'm planning to have community managed type definition repository: major gems will have type definitions • We will have to write type definitions by ourselves for minor gems
  23. Linters and Editors • They will be smarter if integrated

    with Steep • They will know types of variables and expressions • Smarter auto-completion • Better refactoring support • More suggestions for improvements
  24. Is Type Checking Required? • No, it's optional for Ruby

    • There are several levels how you adapt to type checking: • Type check all of your code • Type check part of your code (some .rb files) • Declare types but skip checking implementation • No type declaration but checks your code against gem types • No type checking at all
  25. Conclusion • We are working for type checking for Ruby

    • There are some projects related to types for Ruby • Looking forward to hearing feedbacks from you