-
Notifications
You must be signed in to change notification settings - Fork 82
It's recommended that your initialize
method return C::Any
. It doesn't make much sense to return self
and explicitly define a contract to return Foo
because the return value of initialize
does not affect the return value of the class method Foo#new
(unless you override the class method new
which you very likely won't be doing). Meaning, no matter the return value of initialize
you can do something along the lines of Foo.new.bar
.
class Foo
Contract nil => C::Any
def initialize
@bar = 1
end
def bar
@bar
end
end
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]
.
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