My concept of how (simple) contracts should work was influenced by the Bertrand Meyer / Eiffel approach and spent many years of rolling my own contracts in lesser languages to mimic this.
The main things I found pragmatically useful were: 1. Being able to specify pre-conditions and post-conditions as simple predicates 2. Being able to selectively turn off contracts (typically post-conditions) in well-tested code for performance. With very simple hand-rolled assertions (plus some design discipline) I reckon I achieved 80% pf the promise of contracts, with my debugging time plunging by a factor of 10, and much cleaner designs. When I finally programmed in Eiffel there were several added benefits of language support that I appreciated: - More concise and clear expression of contracts - The implies operator - Proper support for invariant-checking - Proper support for covariant inheritance - Tools for automatically generating documentation - Better tools for turning off contracts by configuration But I was only able to get to use Eiffel in one organisational setting — quite a big negative! * * * Coming across to Racket I was thrilled to see that contracts are a big part of the system, but they are certainly a bit different to what I was used to! I'd like to share a sketch of how I would start to hand-roll the kind of contracts I was used to in Racket. My questions are: - Is it feasible to get similar behaviour from the official contract system?, or - Do these considerations call for building up an alternative system? Restating my goals: 1. Specify pre-conditions and post-conditions as simple predicates (boolean expressions) 2. Selectively turn off contracts (mainly post-conditions) for performance in well-tested code. Example: real square root function, and sketch of support below. Now, I appreciate that the Racket contract system provides all sorts of support for higher-level functional programming, but it concerns me that as a big fan of contracts I've been reluctant to use them consistently in Racket. I hope to change that in my second decade of Racket (formerly PLT Scheme) use, but may need some support and guidance! Dan #lang racket (define pre-conditions-on #t) (define post-conditions-on #t) (define (implies a b) (or (not a) b)) (define-syntax-rule (pre [test? msg] ...) (unless (not pre-conditions-on) (unless test? (error (~a "Pre-condition violation: " msg))) ...)) (define-syntax-rule (post [test? msg] ...) (unless (not post-conditions-on) (unless test? (error (~a "Post-condition violation: " msg))) ...)) (define (real-sqrt x) (pre [(real? x) "real argument expected"] [(>= x 0) "non-negative argument expected"]) (define result (sqrt x)) ; Change the implementation to 1, 0, (- x) to trigger various post-condition errors (post [(implies (= x 0) (= result 0)) "The sqrt of zero should be zero"] [(implies (> x 0) (> result 0)) "Positive numbers have positive square-roots"] [(implies (> x 0) (<= (abs (- x (* result result))) 0.0000001)) "result * result = x (to within error)"]) result) (real-sqrt 0) (real-sqrt 9) (real-sqrt -9) ; Pre-condition error -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.