Indeed this is the case and no; I would not consider it a bug. Because you 
have specified a post condition on the return value, the clojure.core/fn 
macro is macroexpanding properly to support that post condition. By 
recursively macroexpanding the form, you can see the what the form will 
eventually look like to the 
compiler: https://gist.github.com/aamedina/49b4f8caf28c8b78c26b 

If you're using CIDER with Emacs, you can do this on any form by invoking 
M-x cider-macroexpand-all. 

Special forms, like recur, are handled by the compiler as special cases. 
The semantics of Clojure's recur special form forbid it from being used 
anywhere but the tail position of the body of either a fn* or loop*. As you 
can see from the gist, the return value is validated by the number? 
predicate before returning, or else it throws an error.

On Thursday, July 24, 2014 6:56:22 PM UTC-4, Michael O'Keefe wrote:
>
> Hello All,
>
> I encountered the following behavior in Clojure 1.6 and wanted to check if 
> it should be considered a bug or not. I would say yes but wanted to double 
> check on the list first.
>
> Here's a minimal test case that elicited the error:
>
> (defn f
>
>   [xs acc]
>   (if (nil? xs)
>     acc
>     (recur (next xs) (+ (first xs) acc))))
>
> (f [1 2 3 4] 0) => 10
>
>
> Now, if I want to add pre/post conditions, the following happens: 
>
> (defn g 
>
>   [xs acc]
>   {:pre [(or (nil? xs) (sequential? xs)) (number? acc)]
>    :post [number?]}
>   (if (nil? xs)
>     acc
>     (recur (next xs) (+ (first xs) acc))))
>
>
> => this fails to compile with "CompilerException 
> java.lang.UnsupportedOperationException: Can only recur from tail position"
>
>
> In fact, it is only the post-condition that triggers the issue.
>
> My guess would be that the recur statement is being knocked out of tail 
> position by the mechanism for handling the post-condition assertion. It can 
> be fixed in the code by adding an explicit loop:
>
> (defn g2 [xs acc]
>   {:pre [(or (nil? xs) (sequential? xs)) (number? acc)]
>    :post [number?]}
>   (loop [xs xs
>          acc acc]
>     (if (nil? xs)
>       acc
>       (recur (next xs) (+ (first xs) acc)))))
>
>  
> Thanks,
>
> Michael O'Keefe
>

-- 
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to