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
Tweet

More Decks by Soutaro Matsumoto

Other Decks in Programming

Transcript

  1. 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
  2. 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)
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. Write Ruby Program def spots_left? @attendees < capacity end meetup.rb:3:4:

    NoMethodError: type=::Array<::Attendee>, method=< (@attendees < capacity)
  10. 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"
  11. Ruby Programming with Steep • Does it support duck typing?

    • Types of gems? • Linters and editors? • Is type checking required?
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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