There are some optimizations that we can make for the {{simple-ident?}}, {{qualified-ident?}}, {{simple-symbol?}}, {{qualified-symbol?}}, {{simple-keyword?}}, and {{qualified-keyword?}} functions.
Two separate optimization can be done.
In places where {{boolean}} is used (the {{qualified-}} fns), we can instead use {{some?}} for a faster implementation:
(boolean (and (symbol? x) (namespace x) true))
can be converted to simply
(and (symbol? x) (some? (namespace x)))
Focusing on just V8 for now, for
(simple-benchmark [x 'a/b f #(qualified-symbol? x)] (f) 100000000)
and subtracting out the baseline cost for
(simple-benchmark [x 'a/b f (fn [] x)] (f) 100000000)
this yields a speedup of 1.74.
Since we know that we are dealing with keywords or symbols when applying {{namespace}}, we can furthermore use {{(.-ns x)}}.
Alone this gives a speedup of 2.21 and when combined with the previous optimization as
(and (symbol? x) (some? (.-ns x)))
we see a combined speedup approaching infinity (the operation effectively becomes free, taking the same time as the baseline).
Note that we could perhaps use predicate-induced type inference along with a new macro for {{namespace}} that emits {{.-ns}} instead, but CLJS-2866 currently hinges on looking at the test in an {{if}}, while expressions like the above cause optimized {{js*}} output with short-circuiting {{&&}}.
These optimizations would be good because these functions are often used in spec-based generative code testing where performance can be an issue.
We have test coverage for these functions in {{cljs.predicates-test}}.
For reference here is the JavaScript currently emitted for {{qualified-symbol?}}
function cljs$core$qualified_symbol_QMARK_(x) {
return cljs.core.boolean$(
(function() {
var and__8540__auto__ = x instanceof cljs.core.Symbol;
if (and__8540__auto__) {
var and__8540__auto____$1 = cljs.core.namespace(x);
if (cljs.core.truth_(and__8540__auto____$1)) {
return true;
} else {
return and__8540__auto____$1;
}
} else {
return and__8540__auto__;
}
})()
);
}
and here is what we get with the revisions
function cljs$user$qualified_symbol_QMARK_(x) {
return x instanceof cljs.core.Symbol && !(x.ns == null);
}
(The compactness of this revised implementation means that it might be further inlinable via Closure for more speedups for whole-program optimization.)