-
-
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 | |
Why is body
part of the contract? Shouldn't a contract just declare what is required and what is ensured? You give me X and I'll give you Y, we don't specify how I'll get Y from X.
@paraseba
defcontract is unfortunately a poor name for what this is... a better option is something like defcontractedfn. Sorry for the confusion.
I suppose there is no technical reason why the parts should be explicitly ordered. I think if this lib gains any widespread use (crossing fingers) then an idiomatic ordering will fall out of it. However, I'll support arbitrary ordering in any case.
@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 ;-)
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.
I think I'd prefer option 2, if the order has to be set. Even though option 1 seems to follow a natural order of before, during, and after, I think of pre and post conditions as part of the contract, and in my mind they go together.