Silly question (sorry), but is there a reason for key-test to test for (identical? key other) when the next line is (keyword-identical? key other) and that function also tests for (identical? key other)?
I was wondering if it might be because the common case of testing a keyword against itself gets short circuited with the call to identical? instead of having to go into another function to do it. Then again, if that cost mattered, then I thought that testing for identical? twice for non-equivalent keywords would have been an expense.
Then again, maybe it's just such fast execution that issues like double-calling are just left to the VM to clean up?
Never looked at using them for keywords - mostly because they are relatively new feature - but also it would take a bit of work to assess the performance / code size tradeoffs.
Also, it seems strange to be explicitly returning true, and not just defining:
(defn key-test [key other]
(or (identical? key other) (keyword-identical? key other) (= key other)))
(leaving the call to identical? in there still)identical? in CLJS compiles to a very efficient JS check which is basically free
cljs.user=> (str (fn [] (identical? 1 2)))
"function (){\nreturn ((1) === (2));\n}"not completely free, but I think I have yet to meet the first person who made a noticeable optimization by skipping such a test
Yup. I've been looking at the code for the function:
function cljs$core$key_test(key,other){
if((key === other)){
return true;
} else {
if(cljs.core.keyword_identical_QMARK_(key,other)){
return true;
} else {
return cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(key,other);
}
}
}I'm looking for something else, and it just struck me as "odd" that it gets tested for identical? twice
cljs.user=> (keyword-identical? 1 1)
true
;)Then I realized that the cond returning explicit true seemed like a strange pattern as well. There's no problem per se, but I wondered if there was something going on here, and thought I'd ask
google closure would optimize that (the if return true stuff), esbuild would too I think. this is what esbuild makes of it:
function cljs$core$key_test(e,r){return e===r||cljs.core.keyword_identical_QMARK_(e,r)?!0:cljs.core._EQ_.cljs$core$IFn$_invoke$arity$2(e,r)}right there are some patterns you should not copy from core - or generated suboptimal code for a very long time
This is useful to know! Thank you
in general code around the persistent stuff looks odd because it's concerned about codegen
I'm looking at some of the differences between PersistentHashMap on Clojure and ClojureScript. Part of it is due to following:
clj=> (identical? :a :a)
true
cljs=> (identical? :a :a)
false
That shows up in places like https://github.com/clojure/clojurescript/blob/b7ede4bce3e273ab85155fdd8463c291a6f81d43/src/main/cljs/cljs/core.cljs#L7498C17-L7498C49So that's why I'm in that code right now
I do appreciate that keywords differ because ClojureScript doesn't have interning for them
@dnolen did you ever look into https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol for implementing keywords?