This this expression in a clojurescript repl:
(let [{:keys [a-b a_b]} {:a-b 0 :a_b 1}] [a-b a_b])
will surprisingly return:
[1 1]
I did some further investigation by creating a clean project like in Clojurescript official guide:
(ns helloworld.core)
;; two identical code blocks
;; first one is at top level
(let [{:keys [a-b a_b]} {:a-b 0 :a_b 1}] [a-b a_b])
;; second one nested inside a function call
(println (let [{:keys [a-b a_b]} {:a-b 0 :a_b 1}] [a-b a_b]))
and compiled with:
clj -M --main cljs.main --compile helloworld.core
here's the js file:
// Compiled by ClojureScript 1.10.866 {:optimizations :none}
goog.provide('helloworld.core');
goog.require('cljs.core');
var map__528_529 = new cljs.core.PersistentArrayMap(null, 2, [new cljs.core.Keyword(null,"a-b","a-b",-1660985764),(0),new cljs.core.Keyword(null,"a_b","a_b",-1795286609),(1)], null);
var map__528_530__$1 = cljs.core.__destructure_map.call(null,map__528_529);
var a_b_531 = cljs.core.get.call(null,map__528_530__$1,new cljs.core.Keyword(null,"a-b","a-b",-1660985764));
var a_b_532 = cljs.core.get.call(null,map__528_530__$1,new cljs.core.Keyword(null,"a_b","a_b",-1795286609));
new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [a_b_531,a_b_532], null);
cljs.core.println.call(null,(function (){var map__533 = new cljs.core.PersistentArrayMap(null, 2, [new cljs.core.Keyword(null,"a-b","a-b",-1660985764),(0),new cljs.core.Keyword(null,"a_b","a_b",-1795286609),(1)], null);
var map__533__$1 = cljs.core.__destructure_map.call(null,map__533);
var a_b = cljs.core.get.call(null,map__533__$1,new cljs.core.Keyword(null,"a-b","a-b",-1660985764));
var a_b = cljs.core.get.call(null,map__533__$1,new cljs.core.Keyword(null,"a_b","a_b",-1795286609));
return new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [a_b,a_b], null);
})());
//# sourceMappingURL=core.js.map
as you can see:
- the
a-b
and a_b
symbols in first block ended up as var a_b_531
and var a_b_532
.
- in the second block they both ended up as
var a_b
, therefore their values collided.
I also get the same result with macroexpanded version using cljs.core/let*
(let* [m {:a-b 0, :a_b 1}
a-b
(cljs.core/get m :a-b)
a_b
(cljs.core/get m :a_b)]
[a-b a_b])
(println
(let* [m {:a-b 0, :a_b 1}
a-b
(cljs.core/get m :a-b)
a_b
(cljs.core/get m :a_b)]
[a-b a_b]))
so we can eliminate the case that something is wrong with cljs.core/let
macro