contracts.ruby
contracts.ruby copied to clipboard
Allow contractual reference to yet to be defined modules
The following results in an error, despite being completely valid code without the contracts.
class A
Contract None => B
def foo
B.new
end
end
class B
Contract None => A
def foo
A.new
end
end
puts A.new.foo
puts B.new.foo
Sure I could do something like
class A
end
class B
end
at the top of the file, but this is not a good solution.
Honestly, the more I think about it, the more I think contracts belong inside the method. This will make scope issues easier (I think) because contracts are executed within the context of the method anyway. This also could allow ruby to handle issues like #104 naturally.
This is a Ruby issue...you can't use a symbol that isn't defined yet. The following non-contracts code would fail too:
class A
B.new
def foo
B.new
end
end
class B
def foo
A.new
end
end
I'm wondering if the Rec
idea from issue #101 could be used here too. I don't want to include contracts inside a method because that will break multi-dispatch.
Right, I forgot that this gem provides multi-dispatch for a moment. That throws a wrench in the classical contract system.
The problem with using Rec
for these cases, is that Rec
requires you to write the contracts differently, using a string or symbol or something. In the case of recursive datatypes it's unavoidable, but here it should be avoidable. Normally I'd say it's trivial to simply use the namespace of the method, but I haven't given multi-dispatch in this context enough thought.
It would be a shame for people to need to think about the load order of their modules in order to write the correct contracts.
Closing this in favor of #157
I'm sorry maybe I'm being slow but how does #157 solve this?
#157 will add additional syntax that uses isolated namespace and can be evaluated lazily, i.e.:
Contract { [c.Num => MyApp::YetToBeDefined] }
# ...
class MyApp::YetToBeDefined
# ...
end
On the other hand, I think you are right. This still should be opened. And this solution with isolated namespace solves more this issue rather than #157