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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en