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

Reply via email to