Hello, I am not sure that anything has changed between Clojure 1.2.1 and Clojure 1.3.0 with respect to pre- and post-conditions. However, I think I have any idea as to what may be going on.
On Tue Mar 20 05:34 2012, Shantanu Kumar wrote: > Hi, > > The way preconditions are invoked in Clojure 1.3.0 seems to have > changed since Clojure 1.2: > > (defmacro foo > [bar & body] > {:pre [(string? bar)]} > ...) > > (foo "bar34" ...) ; doesn't complain, which is OK > (foo (str "baz" 34) ...) ; Error! (I wanted this to pass) As I understand it, as foo is a macro, bar isn't being evaluated in the precondition. As a result it just gets whatever bar is. In the first example, bar is "bar34", but in the second example, it's the list (str "baz" 34). So, if you changed the precondition to (list? bar), the first would fail, and the second would succeed. > When I write the precondition like this: > > {:pre [`(string? ~bar)]} > > It doesn't seem to check the precondition at all in 1.3.0. In this case, your precondition is evaluating to something like: (clojure.core/seq (clojure.core/concat (clojure.core/list (quote clojure.core/string?)) (clojure.core/list bar))) And this does not evaluate to false. As such, the precondition is being checked, it's just not checking what you want it to check. > Can somebody suggest me what am I missing? I want both the examples > above to be verified and passed as OK. I think what you may want is something like: {:pre [(string? (eval bar))]} However, I must question whether or not you really want to be doing this. The precondition is being evaluated a compile/macro-expansion time, not run time. As such, you should probably only use pre- and post-conditions on defmacro if they are checking the arguments to the macro itself. Just some thoughts. Sincerely, Daniel
signature.asc
Description: Digital signature