Question
In Clojure, it is possible to check if a variable represents a function, using ifn?.
What I'm asking myself is, if there is a way to check if a var is a function which has certain post (or pre) conditions.
Bonus: is it possible to construct the post-condition to be checked parametrically?
Example
Let's say that foo represents a function (i.e. (ifn? foo) returns true).
How can I check that foo has a certain post condition, e.g. that it returns numbers between 0 and 10. In other words, how can I check that foo has the following post-condition?
{:post (and (number? %) (<= 0 %) (<= % 10))
Bonus: is it possible to check for N, instead of 10, where N is a parameter I can choose?
{:post (and (number? %) (<= 0 %) (<= % 10))
Background
I'm implementing Bloom-filter data structure, and it would be really nice if I could validate the hash-functions. (I.e., that they are functions returning only numbers between 0 and the number of bits in the Bloom-filter.)
Remarks
I'm already aware of some workarounds, e.g. like wrapping the hash-functions in other functions that contain the post-conditions, or taking their modulo of the number of bits. While I appreciate any further workarounds for the above use case, please, include an explicit answer to the main question (i.e. "is it possible to check if a function has a certain post-condition?") too. "No, it is not possible" is also an answer I can accept of course.
Yes, building on this Q&A, we can do this:
And write a function taking a function var and a list form to compare to its
:postcondition(s):Then we can test to see if a function has a
:postcondition we expect:This is a very brittle equality test. If you reordered the
andconditions the equality test would fail even though bothands would be logically identical. You could make the test more robust if you wanted.Yes, but again this is going to be brittle/subject to same equality limitations above. In practice, the only difference is we need to specify the form as a kind of template and fill in the blanks before passing it to
some-post?. We can define a function that will replace the symbolNin a form with whatever we want:We can use this with
some-post?like this:As an aside,
(<= 0 % 10)is equivalent to(and (<= 0 %) (<= % 10))but I used your example test verbatim.