Patch submitted @dnolen. I preferred to split into parse-ns-excludes/parse-ns-excludes-impl functions. Otherwise it would format a huge chunk of code
re: Clojure 1.12 method values in ClojureScript. After some more though there is possibly a wrinkle, mostly around interop. We do need to know the arity - for Closure / CLJS that's pretty easy to infer (we already have the machinery). But stuff that Closure won't see is a problem, so we do need :param-tags - but in our the case is the types aren't so meaningful.
I think for interop method values you'll see a lot of ^[Object Object] etc. - not a huge deal - but just noting to see if other folks have thoughts.
@dnolen ^[_ _] is also valid in 1.12
ah ok I missed that? was that written down somewhere?
> Parameters with non-overloaded types can use the placeholder _ in lieu of the tag.
How useful are method values for CLJS anyway?
other thing, Math String are implicit namespaces, but I think this will probably go away and they will be more like implicit refers as they are in Clojure - I pondered the js$ thing and to be honest I'm not a huge fan wrt. language built-ins going back to 2001. Math String Object even Function all provides useful stuff that would be convenient if you just get at them directly, js/ is really a kind of silly thing - they aren't not really foreign - fully covered by Closure for the obvious reasons
I think method values will be useful, again for built-ins I never found the current status quo to be very pleasing
you can already do (map Math/sqrt [1 2 3]) in CLJS
it's also harder to predict future utility for shared libs .cljc - but I think probably be useful.
but w/ a misfeature IMO - implicit namespaces re Math/sqrt
well, (map js/Math.sqrt [1 2 3]) then
that's ugly in two different historical ways
how would you write that without an implicit namespace + js and with method values? I think I'm not getting it yet
nothing would change Math/sqrt - just that Math wouldn't be an implicit namespace anymore
but also stuff like (map ^[_ _] Object/assign seq1 seq2) would work
Why would you need param tags for this though?
cljs.user=> (def Object js/Object)
#'cljs.user/Object
cljs.user=> (map Object.assign [#js {}] [#js {:a 1}])
(#js {:a 1})sorry you're right that case will work, but new is a problem
my take on this is that the Classname/method syntax makes no sense in CLJS given that JS doesn't care what class method comes from to invoke it. So if anything the only thing needed is a generic "interop" way for calling an instance method on an object, without needing to specify the Classname.
the Object.assign case is a bad example since this is not really about calling an instance method, rather a static method
(map .length ["foo" "bar" "baz"])
? ;)what if js/.length
to be clear I'm only interested in more or less doing it the same way (as Clojure)
for example for people doing something very serious they very well might define Java/Closure classes the
same way and just not want to deal w/ reader literals
(map String/substring strs ints) - we don't need param tags in this specific case because of externs, but I think in general you do need them.
what for ... JS doesn't have type based overloading or "reflection" based method calling. we just call the things with arguments and let JS figure it out. This isn't the JVM where it wants to know the exact signature before calling it (or use reflection)
(also not making any decisions yet, but probably I missed stuff, and also happy to collect concerns whether I agree/disagree at the moment)
that's not really true for ClojureScript, we do need to know the arity - performance
that's one of biggest optimizations
so JS doesn't care because it'll happily make yr program go slow
but I do get some of these points about the utility
1. new as fn does seem useful - it's annoying that construction is static in a lot of cases
2. static methods seem useful - and fixes old yucky cases
3. I agree that instance methods are probably not so useful, but I believe in completeness around method values
I mean realistically I cannot think of a case where the Classname is actually relevant to the JS code that needs to run. so for completeness-sake it could just be ignored and just use the name part of the symbol
I don't think a world where AnythingGoesHere/foo is good design, but forcing the user to actually figure out and get a "class" equivalent so the compiler has something to resolve to isn't good either
I'd second the @borkdude example above, but its a bit problematic because (-> "foo" .length) is already allowed and valid but nothing like a method value. not sure this is actually a problem since macro expansion happens before analysis, but still kinda confusing for one thing to become something else entirely depending on context.
gotta step away for a bit, but keep the thoughts coming
(like I said people might rarely use 3. and I don't think this is huge problem, w/ 1. 2., doing 3. is not that much more work)
@souenzzo patch looks ok https://github.com/clojure/clojurescript/pull/240
applied to master
One failed test https://clojure.atlassian.net/jira/software/c/projects/CLJS/issues/CLJS-2292?jql=project%20%3D%20%22CLJS%22%20ORDER%20BY%20updated%20DESC%2C%20created%20DESC - easy to fix, let me know if you want me to handle it
Fixed 🙂