Skip to content

Instantly share code, notes, and snippets.

@fogus
Created June 4, 2010 15:08
Show Gist options
  • Save fogus/425520 to your computer and use it in GitHub Desktop.
Save fogus/425520 to your computer and use it in GitHub Desktop.
(defconstrainedfn sqr
"Calculates the square of a number."
([n]
:requires
(number? n)
(not (zero? n))
:ensures
(pos? %)
:body
(* n n)))
(sqr 6)
;=> 36
(sqr -6)
;=> 36
(sqr 0)
;=> java.lang.AssertionError: Assert failed: (not (zero? n))
(defconstrainedfn positive-floats
"Converts a number to a float. Two numbers to a vector of floats."
([x]
:requires
(number? x)
(pos? x)
:ensures
(float? %)
:body
(float x))
([x y]
:requires
(every? number? [x y])
(every? pos? [x y])
:ensures
(every? float? %)
:body
(str "this is a noop, meant to ensure that multi-expr bodies work")
[(float x) (float y)]))
(positive-floats 1)
;=> 1.0
(positive-floats 1 2)
;=> [1.0 2.0]
(positive-floats -1)
; java.lang.AssertionError: Assert failed: (pos? x)
(positive-floats 1 -2)
; java.lang.AssertionError: Assert failed: (every? pos? [x y])
@goodmike
Copy link

goodmike commented Jun 4, 2010

This may be lead to bloat, but what if my conditions are more complicated than (every? number? [x y])? Would it be reasonable to include an optional string to :requires and "ensures like "each number must be positive"?

@samaaron
Copy link

samaaron commented Jun 4, 2010

It would be very cool if something like this was supported as standard in Clojure. Then it wouldn't be too wild to enhance your favourite text editor's Clojure mode with an ability to expand and hide the pre/post conditions. It would also be nice to have the ability to enable/disable them individually, for a given namespace and globally.

@fogus
Copy link
Author

fogus commented Jun 4, 2010

@goodmike I think a doc string might work, especially when I get around to throwing custom errors. I'm still chewing on this at the moment.

@fogus
Copy link
Author

fogus commented Jun 4, 2010

@samaaron This is a bit of a departure from the current defn, especially with the :body element. I'm still tweaking the syntax but maybe an eye toward eventual Clojure.core consumption would be a nice idea. ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment