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
:post
condition(s):Then we can test to see if a function has a
:post
condition we expect:This is a very brittle equality test. If you reordered the
and
conditions the equality test would fail even though bothand
s 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 symbolN
in 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.