Runtime assertions (like the :pre clause) are the only way to really do this in a dynamic language, but they are merely a band-aid, and suffer these problems:<p>1) You have to actually write the assertion&#x2F;:pre all the time, which is not a trivial step in my opinion. A basic type system just removes this chore altogether. Writing these little assertions really breaks the wonderful flow of elegance.<p>2) Any errors are only caught with a specific input that would violate the assertion; some inputs might pass, and others not. Therefore, you may not know there is a possible bug that will crash your app or lead to unexpected behavior, even if it runs fine for a long time.<p>3) You have to keep flipping the assertions switch on and off as you move from testing to deployment, or, just leave them on and suffer the runtime overhead of their checking everything all the time.<p>4) You will typically write more unit tests to make-up for the tests a type system does for you.