Skip to content
Charles Dale edited this page May 23, 2014 · 8 revisions

It's not obvious what a class initialize should return: self or nil?

initialize returns the value of the last statement. If you don't care about what comes out, use the Any class:

class Foo
  Contract nil => Any
  def initialize
    @bar = 1
  end
end

Note: you might want to return self yourself so you can write statements like Foo.new.bar = "asd":

class Foo
  Contract nil => Foo
  def initialize
    @bar = 1
    self
  end
end

But this is something you have to do yourself, ruby will not do this for you.

It's not obvious what a class setter should return

Again, it will return the value of the last statement, but you might want to return the object instead so you can chain method calls:

Contract String => String
def bar=(val)
  @bar = val
end

It's not obvious if a function argument which is assigned a default value in the signature should be contracted as String, Or[String, nil], or Maybe[String]

Probably you would like String (this will catch the most bugs):

Contract String => nil
def hello(name="adit")
  p "hello, #{name}!"
end

hello

But if you need to support the case where you accidentally get passed an actual nil value, you'll have to do something like this:

Contract Maybe[String] => nil
def hello(name="Adit ")
  name = "" if name.nil?
  p "hello, #{name}!"
end

hello(nil)

Maybe makes it extremely clear that we're capable of handling nil cases. Or was created to handle cases where we're handling two non-nil types: Or[String, Num].

How to specify a fixed length array argument?

Use Array#*. For example, to specify an array of 5 Strings:

Contract(([String] * 5) => Any)

Which Array#* expands to

Contract [String, String, String, String, String] => Any
Clone this wiki locally