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

Attachment: signature.asc
Description: Digital signature

Reply via email to