Open mcandre opened 10 years ago
Update: The problem appears to be specific to unnamed modules with self.
methods. If I give the module a specific name, e.g.:
#!/usr/bin/env ruby
require 'contracts'
include Contracts
module Beer
Contract Num => String
def self.beer(i)
if i >= 3
"#{i} bottles of beer on the wall, #{i} bottles of beer.\n" +
"Take one down, pass it around, #{i - 1} bottles of beer on the wall.\n\n"
elsif i > 1
"2 bottles of beer on the wall, 2 bottle of beer." +
"Take one down, pass it around, 1 bottle of beer on the wall.\n\n"
else
"1 bottle of beer on the wall, 1 bottle of beer.\n" +
"Go to the store and buy some more, 99 bottles of beer on the wall."
end
end
end
def main
99.downto(1).collect { |i| Beer.beer i }.each { |line| puts line }
end
main if $PROGRAM_NAME == __FILE__
Then the problem is mitigated.
Thank you for finding these corner cases!
top-level inclusion of Contracts will be deprecated soon: https://github.com/egonSchiele/contracts.ruby/issues/81
Happens only on global scope and it will be gone once we forbid global inclusion of Contracts
.
Contracts reports a spurious contract violation error, then allows normal execution flow anyway.
Source
https://github.com/mcandre/mcandre/blob/9f587d85754d02f2f10d24062d924d4e427144a9/ruby/beer.rb
Trace
Notes
Seems to me that contracts is mistakenly applying the contract to
#main
rather than#beer
. If I tweak#main
to collect the lines before printing:Then contracts complains:
System