Ruby • Increasingly using Scala whenever I can • Why? – Ruby-like syntax and lack of ceremony – On the JVM – Best bits of Functional and OO paradigms – Powerful statically checked type system
Type systems How do we develop differently in Ruby and Scala? • What are the pros and cons of each? • What are the advantages and disadvantages of types and tests for proving correctness of our programs? • How can types make us better at Ruby?
do type-checks happen? • Runtime (Dynamic) – Blows up in your user's face • Compile time (Static) – Blows up in your own face – Much like your test suite
* x end square("5") $ ruby square.rb TypeError: can't convert String into Integer * at org/jruby/RubyString.java:1135 square at square.rb:2 (root) at square.rb:4
test.scala:3: error: type mismatch; found : java.lang.String("5") required: Int square("5") ^ one error found object Example extends App { def square(x : Int) : Int = x * x square("5") }
extends App { val input = Source.fromInputStream(System.in).getLines for(line <- input) { val n = line.toInt val announcer : _ <: NumberAnnouncer = n % 2 == 0 match { case true => new EvenAnnouncer(n) case false => new OddAnnouncer(n) } println(announcer.announcement) } }
extends App { val input = Source.fromInputStream(System.in).getLines for(line <- input) { val n = line.toInt val announcer : _ <: NumberAnnouncer = n % 2 == 0 match { case true => new EvenAnnouncer(n) case false => new OddAnnouncer(n) } println(announcer.announcement) } }
def initialize(opening_balance) @opening_balance = opening_balance @transactions = [] end def add_transaction(transaction) @transactions << transaction end def balance @transactions.inject(opening_balance) {|b,t| b + t.amount } end end
def initialize(opening_balance) @opening_balance = opening_balance @transactions = [] end def add_transaction(transaction) @transactions << transaction end def balance @transactions.inject(opening_balance) {|b,t| b + t.amount } end end
statements: – “For this specific input, we observe this output” • Types are universally qualified logical statements: – “For all possible inputs, we observe this (type of) output” (modulo non-termination) – Types can make assertions about the call -site of your methods! –
test criteria Can drive design in the small – (But not in the large) – Can document contracts and interfaces – (But not the overall behaviour of a system) The type system complements, rather than replaces your test suite!
type checker for Ruby Rantly (By Howard Yeh) – Quickcheck style fuzz-testing describe "Squaring a number" do context "For all integer inputs" do it "returns a positive integer output" do Rantly { (integer ** 2).should be_greater_than_or_equal_to(0) } end end end