We're updating the issue view to help you get more done. 

some->,some->>,cond->,cond->> and as-> doesn't work with (recur)

Description

some-> and his friends doesn't work with recur, because they never place the last expression in tail position. For example:

1 2 3 4 (loop [l [1 2 3]] (some-> l next recur))

raises UnsupportedOperationException: Can only recur from tail position

This is similar to the bug reported for as-> at http://dev.clojure.org/jira/browse/CLJ-1418 (see the comment at http://dev.clojure.org/jira/browse/CLJ-1418?focusedCommentId=35702&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-35702)

It can be fixed by changing the some-> definition to:

1 2 3 4 5 6 7 8 9 10 11 12 (defmacro some-> "When expr is not nil, threads it into the first form (via ->), and when that result is not nil, through the next etc" {:added "1.5"} [expr & forms] (let [g (gensym) pstep (fn [step] `(if (nil? ~g) nil (-> ~g ~step)))] `(let [~g ~expr ~@(interleave (repeat g) (map pstep (butlast forms)))] ~(if forms (pstep (last forms)) g))))

Similar fixes can be done for some->>, cond->, cond->> and as->.

Note -> supports recur without problems, fixing this will homogenize *-> macros behaviour.

Patch: fix-CLJ-1418_and_1562.patch (code) and 1562-tests.patch (tests)

Screened by: Alex Miller

Examples before/after:

1) (as-> 0 x (inc x))

1 2 3 4 5 ;; before (clojure.core/let [x 0 x (inc x)] x) ;; after (clojure.core/let [x 0] (inc x))

2) (some-> 1 (- 2))

1 2 3 4 5 6 7 8 9 10 ;; before (clojure.core/let [G__5 1 G__5 (if (clojure.core/nil? G__5) nil (clojure.core/-> G__5 (- 2)))] G__5) ;; after (clojure.core/let [G__21 1] (if (clojure.core/nil? G__21) nil (clojure.core/-> G__21 (- 2))))

3) (some->> 1 (- 2))

1 2 3 4 5 6 7 8 9 10 ;; before (clojure.core/let [G__8 1 G__8 (if (clojure.core/nil? G__8) nil (clojure.core/->> G__8 (- 2)))] G__8) ;; after (clojure.core/let [G__24 1] (if (clojure.core/nil? G__24) nil (clojure.core/->> G__24 (- 2))))

4) (cond-> 0 true inc true (- 2))

1 2 3 4 5 6 7 8 9 10 11 12 ;; before (clojure.core/let [G__14 0 G__14 (if true (clojure.core/-> G__14 inc) G__14) G__14 (if true (clojure.core/-> G__14 (- 2)) G__14)] G__14) ;; after (clojure.core/let [G__30 0 G__30 (if true (clojure.core/-> G__30 inc) G__30)] (if true (clojure.core/-> G__30 (- 2)) G__30))

5) (cond->> 0 true inc true (- 2))

1 2 3 4 5 6 7 8 9 10 11 12 ;; before (clojure.core/let [G__11 0 G__11 (if true (clojure.core/->> G__11 inc) G__11) G__11 (if true (clojure.core/->> G__11 (- 2)) G__11)] G__11) ;; after (clojure.core/let [G__27 0 G__27 (if true (clojure.core/->> G__27 inc) G__27)] (if true (clojure.core/->> G__27 (- 2)) G__27))

Environment

None

Status

Assignee

Unassigned

Reporter

nahuel

Labels

Approval

Ok

Patch

Code and Test

Fix versions

Affects versions

Release 1.6

Priority

Critical