ClojureScript

fn/recur bug

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

(defn create-functions [arr names]
  (let [name (first names)]
    (if name
      (recur (conj arr (fn [] (println name)))
             (rest names))
      arr)))
 
(doseq [fn (create-functions [] [:a :b :c :d])] (fn))

Generates the following incorrect code, the local name is not closed over:

cljs_play.let_bug.core.create_functions = function create_functions(arr, names) {
  while (true) {
    var name = cljs.core.first.call(null, names);
    if (cljs.core.truth_(name)) {
      var G__4744 = cljs.core.conj.call(null, arr, function(arr, names) {
        return function() {
          return cljs.core.println.call(null, name);
        };
      }(arr, names));
      var G__4745 = cljs.core.rest.call(null, names);
      arr = G__4744;
      names = G__4745;
      continue;
    } else {
      return arr;
    }
    break;
  }
};

Activity

Hide
Mike Fikes added a comment -

This can be reproduced in master with Nashorn, but not Node. (To be frank, I don't know whether this is a bug in Nashorn, or is what was being sought above, but commenting here just in case.)

$ rlwrap java -jar cljs.jar -m cljs.repl.nashorn
To quit, type: :cljs/quit
cljs.user=> *clojurescript-version*
"0.0-3208"
cljs.user=> (defn cljs-739 [arr names]
  (let [name (first names)]
    (if name
      (recur (conj arr (fn [] (println name)))
        (rest names))
      arr)))
#<function cljs$user$cljs_739(arr,names){
while(true){
var name = cljs.core.first.call(null,names);
if(cljs.core.truth_(name)){
var G__30 = cljs.core.conj.call(null,arr,((function (arr,names,name){
return (function (){
return cljs.core.println.call(null,name);
});})(arr,names,name))
);
var G__31 = cljs.core.rest.call(null,names);
arr = G__30;
names = G__31;
continue;
} else {
return arr;
}
break;
}
}>
cljs.user=> (with-out-str (doseq [fn (cljs-739 [] [:a :b :c :d])] (fn)))
:b
:c
:d
":a\n"

Node, on the other hand, honors with-out-string semantics by not printing anything and returning the string ":a\n:b\n:c\n:d\n".

Show
Mike Fikes added a comment - This can be reproduced in master with Nashorn, but not Node. (To be frank, I don't know whether this is a bug in Nashorn, or is what was being sought above, but commenting here just in case.)
$ rlwrap java -jar cljs.jar -m cljs.repl.nashorn
To quit, type: :cljs/quit
cljs.user=> *clojurescript-version*
"0.0-3208"
cljs.user=> (defn cljs-739 [arr names]
  (let [name (first names)]
    (if name
      (recur (conj arr (fn [] (println name)))
        (rest names))
      arr)))
#<function cljs$user$cljs_739(arr,names){
while(true){
var name = cljs.core.first.call(null,names);
if(cljs.core.truth_(name)){
var G__30 = cljs.core.conj.call(null,arr,((function (arr,names,name){
return (function (){
return cljs.core.println.call(null,name);
});})(arr,names,name))
);
var G__31 = cljs.core.rest.call(null,names);
arr = G__30;
names = G__31;
continue;
} else {
return arr;
}
break;
}
}>
cljs.user=> (with-out-str (doseq [fn (cljs-739 [] [:a :b :c :d])] (fn)))
:b
:c
:d
":a\n"
Node, on the other hand, honors with-out-string semantics by not printing anything and returning the string ":a\n:b\n:c\n:d\n".
Hide
David Nolen added a comment -

I actually can't reproduce this in master - I've added tests to confirm https://github.com/clojure/clojurescript/commit/aaae2688aa2646bb252a9a4dd321e9fa8dbedb6a

Show
David Nolen added a comment - I actually can't reproduce this in master - I've added tests to confirm https://github.com/clojure/clojurescript/commit/aaae2688aa2646bb252a9a4dd321e9fa8dbedb6a
Hide
David Nolen added a comment - - edited

This is because we don't do two passes to determine if a function uses recur. loop/recur works because we know up front.

Show
David Nolen added a comment - - edited This is because we don't do two passes to determine if a function uses recur. loop/recur works because we know up front.

People

Vote (0)
Watch (2)

Dates

  • Created:
    Updated:
    Resolved: