spreadsheet w/ the various global require options https://docs.google.com/spreadsheets/d/1eRyAwvWuHfNUV14ASdZ0gs8ALaU4bQd1kCrpQtzvDlM - I'm totally biased of course, but I did try to be fair wrt. the concerns that I feel are important here when making a decision. Feel free to suggest other aspects to track that I might have missed here.
could you clarify what you mean by the "Method Value Implications" column? that is kinda different from how it works currently, as in only :as is usable as a namespace alias. your examples use :refer though, e.g. (:require [cljs.host.crypto :refer [subtle]]) + subtle/sign. why would that work at all? shouldn't that be limited to things actually setup via :as? or is this just intended as a special case for cljs.host.* (or whatever else it ends up being)?
imho also the namespace resolution should be somewhat locked down, as in not be a namespace at all? cljs.host.crypto/subtle might as well be cljs.host.crypto.subtle and make the whole resolve part much more straightforward
I don't get the "js/ is kinda not good anymore" sentiment. In a podcast some years ago David Nolen praised Rich Hickey for this design decision. I'm missing the reasons why other than "taste" or whatever.
dunno why the js/ example is using js/Foo and not js/crypto.subtle as the rest of the examples, which is already working perfectly fine, meaning for accessing nested values.
"Unsupported - js/Foo/bar not valid" yeah, js/Foo.bar is prefectly fine?
I like js/ and still would much prefer (:require [js/some.thing :as x]) in ns, but I understand the concern that this breaks established specs that likely shouldn't be changed.
what I liked about js is that having a virtual namespace solved a problem, but I don't think I ever claimed it wasn't also an expedience.
Yeah, anything that will cause breakage is just not under consideration. There isn't much in that spreadsheet that makes js/ or js.* look good
> I don't think I ever claimed it wasn't also an expedience Could you elaborate on this?
it's not a real namespace, it takes the slash depriving of it other meanings
which do exist in Clojure, and could exist in ClojureScript
subtle is a singleton, sign is a static method so why wouldn't subtle/sign work (for CLJS 1.12)?
if subtle is :refer-ed then that would be against my expectation from JVM Clojure where a/x only works for classes that are globally defined or imported, or aliases - not for referred vars
I guess for the decisision matrix you could also consider :import for dealing with this.
(:import [crypto subtle])
+ subtle/whatever:import is not important in this matrix, the only reason :import exists in CLJS was because of the namespace as constructor problem
a GCL specific pattern. ClojureScript has always been able to load JS classes via :require so I don't know if your point about a/x is really that relevant here.
(might not be obvious - but anything that's standard in the browser we can figure out from GCL externs, re: methods, static methods / props)
what is relevant from my perspective (and from @thheller’s I assume since he made a similar remark in this thread) is that referred-var/x isn't something that JVM Clojure allows
that part isn't really relevant at all in ClojureScript never was.
ClojureScript collapsed the CLJ namespace / packages problem on day one
:require can in fact handle everything, that difference from CLJ is by design
I think bringing :import into this discussion just confused things. I'm not interested at all in :import. I would completely remove it if it were up to me.
:require can indeed handle everything. but my point was about :refer (x) and then x/foo. which is not currently allowed and IMHO shouldn't be. especially not if only valid for cljs.host.* or whatever it ends up being
not valid only for cljs.host.* never said that anywhere - I tried to be clear that method values are just going to happen.
But I want to solved this global require problem since there are implications
what the heck are "method values" (in this context)?
imo method values introduce more complexity to CLJS for little gain
yes, I know what they mean in Clojure.
I don't want to talk about whether good method values are good or bad, if you don't want to use them - don't use them.
as far I can tell in Clojure there is <Class>/<methodFromThatClass> (or interface for that matter)
but in JS there is rarely a class available?
my point is A) assume method values are going to happen - this means / handling should probably improve
let's drop further discussion about this from this thread
once you accept that, then spreadsheet makes more sense
the method value implication is green on all decisions but the status quo so it seems it doesn't even matter which column is chosen for method values (if they would be added)
so yes, we can leave that out of the discussion
@thheller what do you mean by rarely a class available? are you disregarding GCL?
or GCL externs for the browser?
well "class" is just not as clearly defined in JS is what I mean. Many things have classes but you can't actually get to them (i.e. not exported by a ES module)
right let's put foreign stuff to one side here for a moment.
in the beginning it was just ClojureScript and GCL and very rudimentary support to load a foreign lib. The later was mostly an after thought.
:require was designed to handle everything - and in fact yes I could have avoided :import as a distinct quick fix.
/ was only used for namespaces not because it was intentionally limited by design as far as I could tell, but doing all the inference work via GCC was non-trivial work for an MVP
js/ was an expedient, and that's why js/Foo.bar.baz works because it just wasn't fully solved
To me js/ allows a behavior which I don't love, in Clojure if you want access to a global package you still need to :import it. But in ClojureScript you don't need to do anything. So the we all agree on it would be nice if you could use :require (because we don't need :import)
in Java packages are least namespaced, never single-segment, but in JavaScript the global environment is a grab bag of decades of various apis all at the top level
well yeah, JS just has a lot of built-in globals that you need access to somehow, so js/ is great for that.
right the globals are zero-segment 🙂
js/ gives you one - but again that convention is only nice if it's virtual, and if you don't believe anyone created a namespace
dunno what this has to do with anything though. removing js/ is out of the question no?
oh yeah
I think I need to clarify the method value thing again, or rather how it ties into all of this. (:require [cljs.host.crypto :refer [subtle]]) accesses the crypto.subtle property, which happens to be a singleton instance of SubtleCrypto which would be its class
so if that is now allowed in place of a method value, i.e. something that refers to a class in the namespace part of a symbol
it just adds a whole lot of ambiguity, especially if in this case the correct "type" is actually cljs.host.SubtleCrypto (since that is an actual global)
(:require [some.ns :refer (ARecord)]) then ARecord/something is not valid in CLJ either, or is it? I do not actually know
I think that will probably work?
isn't the basis a static property?
your point about the type is good one though ... need to think about that ... have to step away for a bit.
here is what I mean with an example I guess
$ clj
Clojure 1.12.0
(ns foo)
nil
(defprotocol Foo (something [x]))
Foo
(ns bar (:require [foo :refer (Foo)]))
nil
Foo/something
Syntax error compiling at (REPL:0:0).
No such namespace: Fooi.e. Clojure does not attempt to resolve namespace aliases via refer'd names, but you are proposing that CLJS should?
defprotocol makes this a bit weird since it is actually foo/something, i.e. on the ns not the "class"
dunno if its even possible to create method values for CLJ things. doesn't make much sense given that its all functions already basically
I guess :refer (X) and X/thing is the only proper way to make method values work, if that is the intention. Given that JS doesn't really need to know the type to invoke a function I still do not see the point. But parity I guess i important enough, especially with .cljc in mind.
parity, not usefulness is the driver here
well parity is useful of course, but maybe not useful in your everyday variety
I think the type problem is a great critique of the cljs.host approach, I will think about it a bit more
the ambiguity scares me a bit, since people are going to use it wrong and if that is too relaxed in what it allows things might work but get messy real quick
(:require [cljs.host.crypto :refer [subtle]]) and used as (subtle/sign ...) is just weird and subtle/sign as method value is just weird, because in CLJ it would still expect the thing to invoke that function on as the first arg, whereas here that is not the case
(map subtle/sign ["foo"]) doesn't work since that would technically translate to doing (.sign "foo") with subtle just "gone" since JS doesn't need to type info to know what to invoke
anothing thing I just realized. subtle/sign is perfectly valid in other cases where that is an actual function, i.e. not an instance method of a thing. so the ambiguity just gets out of hand when there is no clear distinction to "I'm refering to a type here" or "this is an alias I setup earlier"
and unlike CLJ we can't check that at compile time to resolve the ambiguity
> in Clojure if you want access to a global package you still need to :import it
this isn't true btw, you can write any class + method as long as you fully qualify it without import?
> in Java packages are least namespaced, never single-segment This unfortunately also isn't true, but it's the exception and bad style to have single segment java packages (I've ran across this issue with clj-kondo which uses the heuristic that single segment isn't java, but unfortunately there are libraries out there who violate this)
re: whether class / type stuff should work w/ :require it seems like really water under the bridge?
i.e. new works
It's not shared publically
if you want to explain how you plan to address my concerns sure ... I'm not against adding it. I'm questioning how.
good questions, but probably will need to dig into the method value concerns later.
Access fixed
great that its also directly enforced by such a meaningless https://github.com/google/closure-compiler/commit/4d32a015b9c90782f49fb95214c0631d3a163056
Would have thought they were lisp programmers.