Fork me on GitHub

on the clojure.math naming issue? Should we not start with cljs.math from the outset? We have automatic aliasing for clojure.* -> cljs.* so clojure.math will still work? When using clojure/math.cljs we eternally have a namespace that cannot ever have macros since clojure/math.clj already exists. It doesn't have macros yet but there might be a point where we want to? even if we just use the macros to do some inlining?


I could see the benefit in changing the simple wrapping functions, e.g.

(defn pow
 [a b]
 (js* "Math.pow((~{}), (~{}))" a b))
I note that this doesn’t need a macro, though from what I can see, functions that use js* are typically defined in the cljs.* namespaces instead of the clojure.* ones. I’m OK with this change, but I’d like to defer to people like David who have a better sense of where things should go.


Why does clojure.math prevent using macros? You could place the macros elsewhere and load them from there?

☝️ 1

ah that's true about inlining macros - @quoll what @thheller is talking about is avoiding a classpath clash - I think that is reasonable


people can still use clojure.math


@borkdude the problem is you need the runtime file and the macros file to have the same name for the ClojureScript compiler to automatically load the macros for consumers of the library


to avoid :require-macros and :require for what is effectively the same library


then for clojure.string shouldn't that also have happened? There might be similar optimizations to be made there using macros


yeah, the same applies there but it predates the pattern of using the self-requiring :require-macros pattern to make macro use "prettier"

👍 1

Sorry, when I talked about the js* form I was thinking about this as the inlining mechanism in macros, and that it would have to be in another file. From what I see here (and seeing how namespaces like core work), then what I think is consistent is to have inlining macros in, say, src/main/clojure/cljs/math.cljc, and that these can be loaded with the existing clojure.math? Is that right? If so, then is it OK that the function-based file stays where it is?


js* is not for inlining. (math/pow 1 2) will still end up as a call to (cljs.math/pow 1 2). you could change the impl to (defn pow [a b] (js/Math.pow a b)) and it would be identical to the js*. the inlining is done by having a macro of the same name that just changes the output to bypass the call to cljs.math/pow


@quoll You're probably aware of this, but if not: CLJS has the concept of macro-fns: a call to a function can go through a macro first, if it's called in function position, while in non-function position it would always fall back on the function implementation. More info here: That allows you to do optimizations, while always being able to refer to the function value as a normal function as well.


@quoll inlining macros are not necessarily about js*


OK, I have my head on with fewer distractions now. Forgetting what I was saying earlier… would it be useful to create a macro like:

(defmacro pow [a b] (list 'Math/pow a b))
? Right now, if something uses (clojure.math/pow a b) in a function it gets converted into:,a,b)
which isn’t ideal


thats only true for non-optimized builds. :advanced builds will have :static-fns true. that'll eliminate the .call. :advanced will also very likely take care of cljs.math.pow and just end up replacing it with the inlined Math.pow directly


I’ve always looked at advanced compilation output to decide


it’s hard to predict what it can eliminate though; if I see it can’t produce good enough code i’ll make a macro to emit code it could do a better job with


IOW a pow macro like you suggest will probably more predictably and consistently produce faster js, but may not actually be necessary to do so, and you lose the ability to redef that var reliably in e.g. a repl (non-advanced compilation) context.


in the first iteration of the loop i=0, j=0 so equalKey is true - then you take the slow path

Alex Miller (Clojure team)16:01:10

yes, it's checking for duplicate key, per the docstring


but it always take the slow path


its looking at index=0


ah, good - thought I was misreading


@fogus @alexmiller thanks! getting close


porting this kind of code over is always an exercise 🙂

fogus (Clojure Team)17:01:52

this one is pretty subtle too IMO

Alex Miller (Clojure team)17:01:27

good as a review for clj side too!!


@quoll left a couple of comments in JIRA

👍 1