On Thu, 2 Aug 2007, Kenneth McDonald wrote:
If you saw an earlier version of this question, apologies…I haven’t seen
it, so assume I accidentally deleted it or it got lost or some such.
In other languages, I’m accustomed to using “assert” as a sort of enforceable
documentation. Is there an equivalent statement or idiom in Ruby? I find that
simply raising exceptions isn’t quite right; exceptions are normally used
when one thinks something might be done about a problem, whereas asserts are
used to check that something is the way it always should be.
I been around this particular block a few times and have come up with
the simplest…
def foo( a)
raise “ASSERTION FAILURE! a ‘#{a}’ not nice!” unless
a.nice?
end
Note a couple of other things…
I have thought about creating an
class AssertionFailure < Exception
end
But I’m not sure I care to. By an assertion failing I’m saying
“Something untoward/unclean has happened. I know not what, I have just
spotted the symptom. Give me some info, give me a backtrace, and I’ll
sort it out later. The program has gone barking mad, take it out back
and shoot it”
Variants on the above, I may change the ASSERTION FAILURE to
PRECONDITION is that’s what I mean…
def foo( a)
raise “PRECONDITION FAILURE! a ‘#{a}’ not nice!” unless
a.nice?
end
Or I may let ruby do it’s thing so instead of
def foo( a)
raise “PRECONDITION FAILURE! a ‘#{a}’ is nil!” if a.nil?
a.doStuff()
end
I prefer…
def foo( a)
a.doStuff()
end
And let Ruby throw the appropriate exception (which gives me a back
trace any way.)
Note I never do something like…
x = ARGV[0].to_f
raise “ASSERTION FAILURE: x ‘#{x}’ is negative” if x < 0
puts x ** 0.5
An assertion failure always means I have may a mistake, never the
user.
In fact some of my scripts have at the end…
rescue Exception => details
puts "This is John’s Fault. Call John now and tell him to fix it.:
puts details.to_s
…
Speedwise I profile, and if one of my asserts show up in a hot
spot… A # or two later it is gone from the execution path, but is
still there as documentation.
Another approach is to try lift the assert up the call tree. Usually
you escape some loop.
def foo(a)
@n.times {|s| bah(s,a)
end
def bah(s,a)
raise “ASSERT FAILURE!” unless a.nice?
do things with s and nice a
end
becomes…
def foo(a)
raise “ASSERT FAILURE!” unless a.nice?
@n.times {|s| bah(s,a)
end
def bah(s,a)
raise “ASSERT FAILURE!” unless a.nice?
do things with s and nice a
end
John C. Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : [email protected]
New Zealand