While playing around with a little test website I came across what, I believe to be a bug in the CLJS compiler. It seems like the generation of symbols for use in macros (e.g. var#) is broken when compiled into certain JavaScript forms.
This is a bit of a contrived example but it illustrates the point. This is my-website.macros file: (ns my-website.macros) (defmacro defalert [name n] `(let [i# ~n] (defn ~name [] (js/alert i#)))) This is my-website.test file: (ns my-website.test (:require [jayq.core :as jq]) (:use-macros [my-website.macros :only [defalert]]) ) (defalert alert5 5) (defalert alert9 9) (alert5) (alert9) And this is (a portion of) the generated .js file: var i__6378__auto__ = 5; my_website.test.alert5 = function alert5() { return alert(i__6378__auto__) }; var i__6378__auto__ = 9; my_website.test.alert9 = function alert9() { return alert(i__6378__auto__) }; my_website.test.alert5.call(null); my_website.test.alert9.call(null); When this is loaded into a webpage two alerts happen (as expected); however, both of the alerts are "9". I believe the intention of the code is to alert 5 and then alert 9. Inspecting the .js generated code it is pretty clear what is going on. The compiler is generating the same symbol for i# in both expansions of defalert and that symbol is being overwritten in the global scope. This seems like a bug to me, but I wanted to get other's opinions. *Additional information* My project.clj looks like: (defproject my-website "0.1.0-SNAPSHOT" :description "Scaffold clojure website" :dependencies [[org.clojure/clojure "1.4.0"] [jayq "0.1.0-alpha4"] [noir "1.3.0-beta3"]] :plugins [[lein-cljsbuild "0.2.9"]] ; cljsbuild plugin :cljsbuild { :builds [{ ;; The path to the top-level ClojureScript source directory: :source-path "src-cljs" ;; The standard ClojureScript compiler options: ;; (See the ClojureScript compiler documentation for details.) :compiler { :output-to "resources/public/js/main.js" :optimizations :whitespace :pretty-print true}}]} :main my-website.server) This example is not as academic as it might first seem. I came across this exact problem while using defpartial from the crate lib by Chris Granger. Here is the code that tripped me up: (defpartial button1 [] [:a.button1 {:href "#"} "Button 1"]) (defpartial button2 [] [:a.button2 {:href "#"} "Button 2"]) (jq/on ($ :body) :click button1 nil (fn [e] (.preventDefault e) (alert "button 1")) (jq/on ($ :body) :click button2 nil (fn [e] (.preventDefault e) (alert "button 2")) My intention was to alert with "Button 1" when any button1 was clicked and to alert with "Button 2" when any button2 was clicked. In this case clicking on any button2 does indeed alert with "Button 2", but clicking on any button1 will also alert with "Button 2". The fundamental problem is due the behavior that I describe in my contrived example. By the way, the workaround here is very easy. Simply replace the button1 and button2 functions in the on calls with the class names assigned to those elements (:.button1 and :.button2 respectively). -- 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