-
-
Save fogus/421387 to your computer and use it in GitHub Desktop.
(defcontractedfn1 sqr | |
"Calculates the square of a number." | |
([n] | |
:requires | |
(number? n) | |
(not (zero? n)) | |
:body | |
(* n n) | |
:ensures | |
(pos? %))) | |
;;;;;; OR | |
(defcontractedfn2 sqr | |
"Calculates the square of a number." | |
([n] | |
:requires | |
(number? n) | |
(not (zero? n)) | |
:ensures | |
(pos? %) | |
:body | |
(* n n))) | |
;;;;;; OR | |
(defcontractedfn3 sqr | |
"Calculates the square of a number." | |
([n] | |
:requires | |
number? | |
(not (zero? n)) | |
:ensures | |
pos? | |
:body | |
(* n n))) | |
(sqr 0) | |
; java.lang.AssertionError: Assert failed: (not (zero? n)) | |
(sqr 7) | |
;=> 49 | |
(sqr -7) | |
;=> 49 | |
How about adding other keywords that act like ->
macro?:
:ensure-> pos? even?
Of course :ensure->>/:requires->>
would be available too
I think I will keep the keywords as is and instead prefer that ->
/->>
be used explicitly. However, one thing I was playing with was allowing functions to be used directly which implicitly means that in the case of :requires
the args are passed in and with :ensures
the return. That way you can write something like defcontracted3
.
Cool! how will you enable/disable the checks?
I'm not sure I follow.
ensure and require conditions are always checked and enforced? Can I opt out of that behavior, for instance for performance reasons in production environments?
I see what you mean. Nothing will happen if *assert*
is set to false
. In fact that pre and post conditions will not even be generated.
@fogus I totally agree. I'm all in favour of encouraging idioms rather than enforcing them. But then I used to be a Rubyist rather than a Pythonista - so that's to be expected ;-)