Using an explicit eval is generally not a good idea, as `bar` will be evaluated 
at least twice: once in validating the precondition, and again in the 
macroexpansion.  This can lead to all sorts of "interesting" problems if `bar` 
happens to be a side-effecting expression.

- Chas

On Mar 20, 2012, at 9:18 AM, Daniel Solano Gomez wrote:

> 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
> 

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to