cljs-dev

ClojureScript compiler & std lib dev, https://clojurescript.org/community/dev
frozar 2020-04-24T09:09:07.216800Z

@dnolen Hi, I would like to discuss (again I know) about the :default require keyword. I followed the issue at: https://clojure.atlassian.net/browse/CLJS-2376 And I understand why you are not inclined to support it in cljs compiler. In my situation, I'm working around the cljdoc project, and some of the analysed package contains the :default keyword in their requirement. In this case, the cljdoc-analyzer, which relies on the cljs parser facilities, just throws an exception during its execution. My question is: Is the support of :default keyword in the cljs parser definitely rejected? Or is it still in the balance? A strategy should be adopted in cljdoc from there to deal with :default keyword. (ping @martinklepsch)

thheller 2020-04-24T09:20:05.218Z

I typically advise people not to use :default in libraries so maybe the lib authors should just use the alternative :rename {default foo} instead of :default foo?

frozar 2020-04-24T09:35:22.218900Z

Why not, it's possible. It's a way to deal with it. So the :default keyword from shadow-cljs is deprecated?

thheller 2020-04-24T09:36:38.219700Z

no, it isn't. just makes libs shadow-cljs only which I lib authors should avoid (IMHO)

frozar 2020-04-24T09:45:09.220900Z

Ok, if you advice to avoid it, so if cljdoc doesn't support this keyword, it's pretty reasonable, no?

martinklepsch 2020-04-24T09:46:00.221500Z

Yes, I think supporting :default would be outside the scope for cljdoc since the library would be only usable from shadow anyways

frozar 2020-04-24T09:52:29.221800Z

Ok, I have to fix my lib πŸ˜›

dnolen 2020-04-24T10:58:00.222600Z

one alternative for the :default thing just always do the rename bit for Node.js libs?

dnolen 2020-04-24T10:58:32.223200Z

Could be done for ES6 libs too of course if we detect them.

dnolen 2020-04-24T10:59:16.224100Z

The thing I wanted to avoid with CLJS-2379 is more new stuff in the ns form - but if we just automatically do this would avoid the need for that

dnolen 2020-04-24T10:59:21.224400Z

similar to what we do for invokeable nses

thheller 2020-04-24T11:19:52.225100Z

what do you mean by automatic? I mean how would you know whether a react-native package has a default export or not?

dnolen 2020-04-24T12:41:18.226500Z

right we would need to add that metadata, I thought our node_modules processing looked at exports

dnolen 2020-04-24T12:41:26.226700Z

or could be easily modified to do so

dnolen 2020-04-24T12:41:57.227Z

this doesn't seem very hard to do - i.e. Rollup

dnolen 2020-04-24T12:43:18.227400Z

in anycase this is the only kind of solution I would find acceptable - nothing manual

dnolen 2020-04-24T12:43:51.227800Z

happy to see someone take this one - I would say medium difficulty

dnolen 2020-04-24T12:44:11.228300Z

not too many changes to ClojureScript once the parsing problem is solved

dnolen 2020-04-24T12:51:15.228900Z

https://clojure.atlassian.net/browse/CLJS-2376 ticket updated, @juhoteperi I'm assuming you don't still want to be assigned to this one quite old

dnolen 2020-04-24T12:58:47.229900Z

I'm planning on cutting a release today - haven't head any bad news and all the latest changes are just to support downstream tooling

dnolen 2020-04-24T13:25:15.230300Z

1.10.738 being built now

2020-04-24T13:26:45.230700Z

hmmm, I'm seeing cljs.core/+, all arguments must be numbers, got [clj-nil number] instead for (s/coll-of ::menu-item :kind sequential? :min-count 1)

dnolen 2020-04-24T13:29:50.231500Z

@roman01la make something minimal and file a ticket, would be nice to know if that's a regression of some kind since we messed w/ this stuff recently

dnolen 2020-04-24T13:38:45.232200Z

@roman01la yeah that was definitely one of the patches clj-nil not considered a number type anymore

2020-04-24T13:39:10.232800Z

Am I doing something wrong here?

clj -Sdeps '{org.clojure/clojurescript {:git/url "<https://github.com/clojure/clojurescript.git>" :sha "b79007367818f0d1567646f28f09e2de3450a99e"}}' -m cljs.main -v -re node

Execution error (FileNotFoundException) at clojure.main/main (main.java:40).
Could not locate cljs/main__init.class, cljs/main.clj or cljs/main.cljc on classpath.

2020-04-24T13:39:26.233200Z

I think that was my patch

alexmiller 2020-04-24T13:39:58.233800Z

you're missing the :deps level

alexmiller 2020-04-24T13:40:11.234100Z

clj -Sdeps '{:deps {org.clojure/clojurescript ....

mkvlr 2020-04-24T13:40:23.234400Z

right clj -Sdeps '{:deps {org.clojure/clojurescript {:git/url "<https://github.com/clojure/clojurescript.git>" :sha "b79007367818f0d1567646f28f09e2de3450a99e"}}}' -m cljs.main -v -re node

2020-04-24T13:40:23.234500Z

ah I see, thanks

dnolen 2020-04-24T13:40:53.234700Z

@roman01la I'm going to revert your patch

dnolen 2020-04-24T13:41:08.235100Z

if you could reopen the ticket and add that would be helpful

2020-04-24T13:41:15.235300Z

sure

dnolen 2020-04-24T13:46:10.235500Z

building 1.10.739

dnolen 2020-04-24T13:50:21.235800Z

website updated with release post

dnolen 2020-04-24T13:50:53.236600Z

@alexmiller I want to do a post after that is there an easy way to have a post come afterwards with AsciiDoc even though the date is the same?

alexmiller 2020-04-24T13:53:13.236900Z

not to my immediate knowledge

alexmiller 2020-04-24T13:53:37.237200Z

there's a date sort somewhere

alexmiller 2020-04-24T13:59:57.238Z

2009/05/17 17:58:44
a format like that might work to set an explicit time for the post

alexmiller 2020-04-24T14:00:04.238200Z

let me try it

dnolen 2020-04-24T14:00:47.238400Z

cool thanks

alexmiller 2020-04-24T14:03:56.238800Z

that seems to sort and appear correctly for me if I use 2020-04-24 23:59:59

alexmiller 2020-04-24T14:04:11.239200Z

but may just be coincidence, not totally sure

alexmiller 2020-04-24T14:04:27.239500Z

do you want me to push current site or wait?

dnolen 2020-04-24T14:08:51.239800Z

wrapping up the others posts

dnolen 2020-04-24T14:08:54.240Z

one moment

alexmiller 2020-04-24T14:09:48.240300Z

just ping me

dnolen 2020-04-24T14:22:45.240500Z

@alexmiller fire away

dnolen 2020-04-24T14:44:06.241300Z

@alexmiller just added some missing updates - let me know when it's ready and I will post updates to various channels

dnolen 2020-04-24T16:25:35.242300Z

bunch of issues around the js-iterable? predicate, took a few tries to sort that out

dnolen 2020-04-24T16:25:51.242900Z

1.10.741 should be appearing relatively soon

dnolen 2020-04-24T16:26:11.243200Z

I updated the website to reflect the new version

dnolen 2020-04-24T16:35:34.244100Z

stepping away for a little bit I believe everything should be ready to go - please try 1.10.741 when it appears would love to address any straggling issues if they come up today

alexmiller 2020-04-24T16:41:27.244700Z

@dnolen sorry, was heads down on other stuff, will push site

alexmiller 2020-04-24T16:44:08.244900Z

pushed

alexmiller 2020-04-24T16:44:34.245100Z

https://clojurescript.org/news/2020-04-24-release

alexmiller 2020-04-24T16:44:39.245300Z

https://clojurescript.org/news/2020-04-24-bundle-target

dnolen 2020-04-24T17:05:27.245500Z

Thanks!!!

dnolen 2020-04-24T17:21:15.245900Z

@alexmiller minor typo, another push whenever you can

alexmiller 2020-04-24T17:26:31.246100Z

Will do

dnolen 2020-04-24T19:18:29.246700Z

@thheller I don't really understand your concerns about handling exports when stuff like this exists https://github.com/rollup/plugins?

dnolen 2020-04-24T19:19:12.247700Z

given the years of prior art - this doesn't seem problematic to me, your comments so far seem to be ignoring this?

dnolen 2020-04-24T19:27:00.248Z

@alexmiller another bump on the site, typo in the webpack guide

alexmiller 2020-04-24T19:30:08.248200Z

button pushed

dnolen 2020-04-24T19:56:07.250100Z

seems like you could even just do this with Rollup.js directly

dnolen 2020-04-24T20:01:45.250700Z

another possibility

dnolen 2020-04-24T20:02:32.251600Z

but as I expected JS already had to work around the chaos

thheller 2020-04-24T20:04:14.252900Z

@dnolen the point I have about default is that I want something that DIRECTLY corresponds to a JS feature that is here now and used in libraries and probably more to come in the future as more people move to ESM

thheller 2020-04-24T20:04:59.253700Z

it isn't even about how we process that, it is about being able to access it in a user friendly manner which IMHO :default foo does better than :rename {default foo}

thheller 2020-04-24T20:05:21.254200Z

I understand you don't want to add stuff to the ns form and I'm fine with that ... don't do it then

thheller 2020-04-24T20:05:38.254800Z

but adding compiler magic or adding third party tools does not address this problem in any way whatsoever

dnolen 2020-04-24T20:06:05.255600Z

the :rename thing is not so import

thheller 2020-04-24T20:06:11.256Z

it is just about " how do I refer to this thing that library exports" nothing more

dnolen 2020-04-24T20:06:13.256100Z

how it is accomplished isn't meaningful

dnolen 2020-04-24T20:06:17.256300Z

"3rd party" is irrelevant

dnolen 2020-04-24T20:06:22.256500Z

Closure is 3rd party thing

dnolen 2020-04-24T20:06:38.256900Z

how it is detected is an implementation detail

dnolen 2020-04-24T20:06:58.257200Z

so when we discuss it that's what I'm interested in

dnolen 2020-04-24T20:07:09.257600Z

not talking about irrelevant implementation details - but the end result

dnolen 2020-04-24T20:07:29.258500Z

if you require a library that exports default it can be used as a namespace

dnolen 2020-04-24T20:07:38.259Z

w/o accessing a property

thheller 2020-04-24T20:07:55.259300Z

what? no it cannot?

thheller 2020-04-24T20:08:13.260Z

how do you mirror import * as thing from "foo" then if :as is already "used for default"?

dnolen 2020-04-24T20:09:09.261400Z

let's rewind a bit

dnolen 2020-04-24T20:09:14.261700Z

before talking past each other

thheller 2020-04-24T20:09:25.262200Z

import Thing, * as everything from "foo";

dnolen 2020-04-24T20:09:41.262600Z

I think you actual problem w/ the proposal is that in JS you have a choice

dnolen 2020-04-24T20:09:59.263Z

and choosing anything flies in the face of being able to choose in JS

thheller 2020-04-24T20:10:12.263200Z

I don't follow

dnolen 2020-04-24T20:10:29.263600Z

let's stop talking about import

dnolen 2020-04-24T20:10:34.263800Z

just about how we want to use X from CLJS

dnolen 2020-04-24T20:10:42.264Z

some thing exports default

dnolen 2020-04-24T20:10:51.264300Z

in JS I don't have to talk about default when I import

dnolen 2020-04-24T20:11:04.264700Z

I just get a ns-y thing

dnolen 2020-04-24T20:11:15.265200Z

that would be preferred in CLJS

thheller 2020-04-24T20:11:21.265400Z

I don't follow sorry. you mean you don't have to use the word default?

dnolen 2020-04-24T20:11:39.265800Z

you don't have to use default when you import in JS

dnolen 2020-04-24T20:11:45.266200Z

so why should you have to use it in CLJS?

thheller 2020-04-24T20:11:53.266500Z

yes, because it has dedicated syntax for it?

thheller 2020-04-24T20:12:10.267400Z

like literally import &lt;defaultExport&gt; from "foo"?

thheller 2020-04-24T20:12:21.267900Z

import Thing, * as everything from "foo"; this is actual valid JS?

dnolen 2020-04-24T20:12:35.268400Z

and does that fail if you don't export default?

thheller 2020-04-24T20:12:36.268500Z

and would be (:require ["foo" :as everything :default Thing])

thheller 2020-04-24T20:13:29.269Z

I'm lost again? that import will fail if the library has no default export yes?

dnolen 2020-04-24T20:14:45.269900Z

just trying to parse that expression

dnolen 2020-04-24T20:15:06.270700Z

it's imports the default under one name, then all other exported symbols into a different bag called everything

thheller 2020-04-24T20:15:08.270900Z

all I'm looking for is being able to express all the variants of import that the ESM spec has

dnolen 2020-04-24T20:15:34.271700Z

yeah not necessarily interested in that

thheller 2020-04-24T20:15:37.272Z

import Thing, {foo, bar} from "foo" is also valid

dnolen 2020-04-24T20:15:44.272300Z

because of impedance mismatch

thheller 2020-04-24T20:15:51.272600Z

what does that mean?

dnolen 2020-04-24T20:16:04.272900Z

adding more stuff to the ns form

dnolen 2020-04-24T20:16:09.273100Z

that isn't Clojure stuff

dnolen 2020-04-24T20:16:18.273400Z

that's the hard design constraint

thheller 2020-04-24T20:16:42.273800Z

so host-interop doesn't matter? I mean we have :refer-macros and other stuff clojure doesn't have?

dnolen 2020-04-24T20:17:28.274700Z

sure but old days, we reconciled that with sugar long ago for .cljc

dnolen 2020-04-24T20:17:32.274900Z

nobody wants to go backwards

dnolen 2020-04-24T20:19:04.275700Z

Clojure has some prior art here w/ harder things to import, inner classes in packages

dnolen 2020-04-24T20:19:08.276Z

Foo$Bar

dnolen 2020-04-24T20:19:23.276600Z

what about foo$default and "foo$default" ?

thheller 2020-04-24T20:19:58.277100Z

give me a full example please. not really sure what you mean? as a separate require?

dnolen 2020-04-24T20:20:13.277700Z

yes

thheller 2020-04-24T20:21:34.278900Z

I don't like it. Just makes things more complicated to explain IMHO

thheller 2020-04-24T20:21:51.279400Z

I made a translation table here https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages

dnolen 2020-04-24T20:21:58.279600Z

without more elaboration that's not much of an argument

thheller 2020-04-24T20:22:29.280500Z

see ES6 Import to CLJS Require so that people can look at a JS example of how to use a certain library

thheller 2020-04-24T20:22:37.281100Z

and have a direct translation of how you do that in CLJS

dnolen 2020-04-24T20:22:55.282Z

sure but that's not compelling argument

dnolen 2020-04-24T20:23:10.282600Z

anyways the end result is something that would get the same result w/o futzing w/ the ns form

thheller 2020-04-24T20:23:18.283200Z

I cannot make a compelling argument if you have already decided that you are not going to add :default

dnolen 2020-04-24T20:23:32.283600Z

I've consistently rejected adding another thing for a couple years πŸ™‚

dnolen 2020-04-24T20:23:39.283800Z

not gonna change my mind now

thheller 2020-04-24T20:23:49.284300Z

then I don't know why we are even talking

dnolen 2020-04-24T20:23:58.284500Z

but open to feedback about stuff that doesn't mess w/ the ns form

dnolen 2020-04-24T20:24:40.285500Z

the other thing about foo$default is that it's trivial to implement

dnolen 2020-04-24T20:24:44.285800Z

also trivial to support downstream

dnolen 2020-04-24T20:25:35.287100Z

so there's a compatible way that libs/apps can use w/o caring

thheller 2020-04-24T20:26:27.287900Z

I don't like it. I think it is needlessly confusing when we can express this nicely with actual syntax data and not magic strings

dnolen 2020-04-24T20:26:52.288600Z

your feedback has been heard - now many times πŸ™‚

dnolen 2020-04-24T20:26:57.288800Z

anyways let other people chime in

dnolen 2020-04-24T20:27:50.291200Z

foo$default and "foo$default" semantically would let us get at the default export as a namespace-y thing

dnolen 2020-04-24T20:28:14.293Z

there's prior art in Clojure inner class import as well as CLS bootstrap foo$macros

dominicm 2020-04-24T20:28:54.295200Z

I don't think I'd have too much problem adding the $default syntax to that table. I find it weird to use a namespace directly as a variable, but I know that's already there.

slipset 2020-04-24T20:30:42.297300Z

Being more of a clj than a cljs dev, I find the finer details of jvm interop something I encounter very seldom. Most things I need are wrapped in a (thin) clj wrapper. Reason I’m mentioning this is that maybe this is the case with cljs as well, and if so, maybe it doesn’t matter too much if the syntax is a bit idiosyncratic?

dominicm 2020-04-24T20:31:39.298600Z

@slipset I wouldn't say that's too true. There's a large number of npm packages, and they cover a broad scope. We use a large number of npm packages currently.

lilactown 2020-04-24T20:35:49.302200Z

my personal feelings right now is that it would behoove CLJS to pave the path to using standard JS

lilactown 2020-04-24T20:37:54.303500Z

ESM is not a moving target anymore, I think that laying some concrete on how syntactically we can translate between the JS and CLJS ecosystem helps a lot with onboarding and helping people feel productive

lilactown 2020-04-24T20:41:32.304400Z

I think some of this discussion is brought on by the fact that tools like webpack have been very liberal in parsing ESM imports in the past

lilactown 2020-04-24T20:42:16.305300Z

import React from "react" does work sometimes but it’s actually not valid, it should be import * as React from "react" but tools like webpack just let you get away with the former

thheller 2020-04-24T20:42:56.306100Z

I'd be careful with that statement. It is still not "final" on how CommonJS <> ESM is ultimately going to work

thheller 2020-04-24T20:43:29.306600Z

so import React from "react" is actually correct as long as react only ships CJS code

thheller 2020-04-24T20:44:06.307200Z

but since no browser even supports that option and likely never will its always going to stay a bundler thing

lilactown 2020-04-24T20:44:38.307800Z

there was a twitter thread where they were really encouraging people to use the actual ESM ns form instead of the default form (that relies on CJS interop)

lilactown 2020-04-24T20:44:55.308200Z

and that they would be moving the docs / create-react-app to reflect this

lilactown 2020-04-24T20:45:24.309300Z

probably because they really want to ship ESM but can’t because the ecosystem is still so choatic

thheller 2020-04-24T20:45:40.309600Z

again .. thats a bundler thing and webpack keeps changing their mind on this. they want to release it with strict-mode and have been talking about breaking changes for a while now ... yet still no webpack v5

thheller 2020-04-24T20:46:02.310Z

react doesn't ship ESM because they want to do stuff you can't do with ESM

thheller 2020-04-24T20:47:24.310700Z

like this conditional require of the minified bundle https://unpkg.com/react@16.13.1/index.js

thheller 2020-04-24T20:47:41.311100Z

you cannot do this with ESM .. you need import maps for that ... but that is yet another unfinished spec

lilactown 2020-04-24T20:48:36.312Z

I see. I misspoke

thheller 2020-04-24T20:49:08.312900Z

really I have no hope for this ever to work out

thheller 2020-04-24T20:49:39.313700Z

the only clear way out of this is to have everything as ESM ... but that is going to take ages ... so we live in chaos πŸ˜‰

lilactown 2020-04-24T20:50:39.315300Z

my point was that JS devs do have to make a choice, based on the standards, and that bundlers have been inconsistent in their approach to all of this.

lilactown 2020-04-24T20:51:00.315800Z

but we should pave the path to using standard JS

lilactown 2020-04-24T20:51:16.316100Z

my personal dream would be that I could copy + paste an ESM into the source path of my CLJS project and it would Just Work:tm:, and things that require bundling (commonjs, other garbage from npm that requires transpiling) I can use shadow-cljs/rollup/whatever

❀️ 1
thheller 2020-04-24T20:51:50.316800Z

you can do that today. just can't also mix in some random npm commonjs code (eg. react)

lilactown 2020-04-24T20:52:05.317200Z

right, but the importing thing we’re talking about above comes into play right?

thheller 2020-04-24T20:52:16.317700Z

if you have all ESM it does not no. the interop/mix is the issue. all ESM or all CJS is totally fine.

lilactown 2020-04-24T20:52:59.318300Z

I thought y’all were talking about how to refer to default imports in an ESM

lilactown 2020-04-24T20:54:07.319400Z

the actual point I’m circling around is that I agree with adding a :default import πŸ˜„

thheller 2020-04-24T20:55:10.320700Z

you can still use it regardless of :default. It really is just syntax sugar for :refer (default) :rename {default foo}. can't remember if the :refer was actually necessary so may just be :rename {default foo}

dominicm 2020-04-24T20:55:59.321700Z

Remind me why we need sugar?

dnolen 2020-04-24T20:56:49.322500Z

because the :rename trick brings in an object not a namespace thing

dnolen 2020-04-24T20:57:03.322900Z

foo$default :as foo would support foo/api

dnolen 2020-04-24T20:57:20.323800Z

and you could use it in combination with [foo :as f]

dominicm 2020-04-24T20:58:04.325900Z

I'm a little out of touch with esm, if you do import x from "y" does x.z make sense for all things?

dnolen 2020-04-24T20:58:06.326Z

this about about using JS libs as namespaces

dominicm 2020-04-24T20:58:32.326800Z

I'm assuming default could be a string.

dnolen 2020-04-24T20:58:41.327300Z

there's another interesting idea here

thheller 2020-04-24T20:58:56.327900Z

Its usually a single object like a class or so. haven't seen a case where that be an actual "namespace"

1
dnolen 2020-04-24T20:59:19.328900Z

which I floated around before which is that foo$default might not need to be specific to ES6

dnolen 2020-04-24T20:59:30.329500Z

another reason I don't really like :default that much

thheller 2020-04-24T20:59:30.329600Z

only in the cases where CommonJS is actually imported that way .. so import React from "react" and React.createElement

dnolen 2020-04-24T20:59:44.329900Z

someGlobal$bar would be possibility

dnolen 2020-04-24T20:59:59.330200Z

i.e. some JS object on the page that's global

dnolen 2020-04-24T21:00:09.330500Z

and you could get externs infer for that too

dnolen 2020-04-24T21:00:24.330800Z

rather than naked js/...

dnolen 2020-04-24T21:01:10.331900Z

so that's another to weigh, Foo$Bar could be generic pattern rather hard coded to default problem

thheller 2020-04-24T21:02:14.332300Z

@dnolen not sure what you are talking about

lilactown 2020-04-24T21:05:48.335800Z

so you could do (:require [window$AbortContoller :as AbortContoller]) ?

lilactown 2020-04-24T21:06:56.336100Z

what about using :import?

dnolen 2020-04-24T21:09:27.336700Z

@lilactown yes all these standard apis could be required as namespaces

dnolen 2020-04-24T21:09:31.336900Z

it would cleanup usage

dnolen 2020-04-24T21:10:00.337500Z

@lilactown (:import ...) is really just a hack for GCL

dnolen 2020-04-24T21:10:11.337800Z

because the namespace can be an object which is really annoying

dnolen 2020-04-24T21:10:56.338500Z

@lilactown I don't think Foo$Bar pattern can help much with that

dnolen 2020-04-24T21:11:53.339500Z

anyways I'm warming up to Foo$Bar because it's more general, and default falls out of it, instead of being designed for it

dnolen 2020-04-24T21:12:23.339900Z

wanting to treat some property as a namespace is a generally useful thing

lilactown 2020-04-24T21:14:29.340800Z

how will it work with imports that are strings? "@corp/my-lib$default" seems gross to my eyes

dnolen 2020-04-24T21:15:18.341700Z

would be exactly the same, and again not specific to default

dnolen 2020-04-24T21:15:36.342100Z

you could get at anything in that lib as a namespace

dnolen 2020-04-24T21:15:53.342700Z

introducing novelty to the delimiter here is not that interesting to me

dnolen 2020-04-24T21:16:00.343200Z

Clojure already has a pattern we already use it

lilactown 2020-04-24T21:16:03.343400Z

and I guess, IMO it would be better for external analysis to not have to parse strings / symbols

thheller 2020-04-24T21:16:04.343500Z

so we are not modifiying the ns because :default is "new" but we are adding a whole bunch of magic for accessing nested properties?

dnolen 2020-04-24T21:16:18.343800Z

"whole bunch of magic"

dnolen 2020-04-24T21:16:38.344300Z

this isn't a very challenging change we already have everything to return whatever from a resolve

thheller 2020-04-24T21:17:16.345200Z

I mean adding new functionality to ns. not talking about implementation at all, I know that is trivial.

dnolen 2020-04-24T21:17:38.345700Z

it's really a change to resolve

dnolen 2020-04-24T21:17:40.346100Z

barely a change to ns

lilactown 2020-04-24T21:18:18.346900Z

yeah I think the semantics of a keyword vs a special string/symbol are not really different to me as a consumer, which I think is what thheller means

thheller 2020-04-24T21:18:35.347400Z

I think regular JS interop is fine for this don't know why the ns/resolve would need gain that functionality

thheller 2020-04-24T21:19:48.348300Z

don't even want to think about an npm package that has an actual $ in its name. I'm sure there exists one πŸ˜›

dnolen 2020-04-24T21:22:48.350500Z

@lilactown I'm already talking about bigger problem now

dnolen 2020-04-24T21:22:59.351100Z

the discussion was just think about the default problem

dnolen 2020-04-24T21:23:10.351700Z

but now maybe a more general issue to solve

dnolen 2020-04-24T21:23:42.352800Z

the default issue is the same as many other things you can't practically require

dnolen 2020-04-24T21:23:52.353400Z

that requires going to globals or accessing objects

lilactown 2020-04-24T21:25:17.356Z

I am tracking your thoughts I think. I disagree with the ergonomics of using a special $ delimiter

thheller 2020-04-24T21:25:17.356100Z

@dnolen just so I understand what you are proposing. suppose there is a npm package that exports something nested like react-native :as rn rn/AppRegistry.registerComponent. you want (:require [react-native$AppRegistry :as reg]) reg/registerComponent?

thheller 2020-04-24T21:27:21.356900Z

I don't hate the idea but this definitely falls into the magic category for me.

thheller 2020-04-24T21:29:58.357700Z

scratch that ... I don't like magic characters.

lilactown 2020-04-24T21:30:41.358500Z

(ns <http://corp.app|corp.app>
  ;; add a new `:with` keyword that provides the behavior
  ;; to use a JS property as an ns, provide externs, etc.:
  (:require ["@corp/my-lib" :as my-lib :with [default :as my-lib-default]]
            [window :with [AbortController]]))

lilactown 2020-04-24T21:31:26.359200Z

the difference between :with and :refer / :rename is that the symbol would be treated as a namespace, not a value

thheller 2020-04-24T21:31:28.359400Z

@lilactown noooooooooooooooo πŸ˜›

lilactown 2020-04-24T21:31:34.359600Z

πŸ˜„

dnolen 2020-04-24T21:40:21.360200Z

@thheller this is no longer about just node_modules

dnolen 2020-04-24T21:40:36.360500Z

it does not matter what require you are using, it would work

dnolen 2020-04-24T21:41:01.360900Z

there's nothing magical about it, it's just a custom resolve

dnolen 2020-04-24T21:41:07.361200Z

it's almost identical to inner classes in Clojure

dnolen 2020-04-24T21:41:16.361600Z

there something in a package that you want to refer to, but it's impractical

dnolen 2020-04-24T21:41:55.362200Z

in this case there some property in JS which is effectively a namespace

dnolen 2020-04-24T21:42:12.362800Z

i.e. a global, i.e. a property, i.e default, it doesn't not matter

dnolen 2020-04-24T21:42:20.363100Z

it would be better to use that thing as a namespace from ClojureScript

dnolen 2020-04-24T21:42:54.363600Z

so less interested in now in feedback about default problem

dnolen 2020-04-24T21:43:12.364200Z

more interested in feedback about a problem in literally all ClojureScript codebases right now

dnolen 2020-04-24T21:43:48.364800Z

tons of libraries / apps right now accessing properties which are just namespaces, global which are just namespaces

thheller 2020-04-24T21:43:54.365Z

I'm not asking about node_modules. I used that as an example of how the actual syntax is supposed to look

dnolen 2020-04-24T21:45:05.366100Z

it would only work on the ns identifier itself nowhere else, and probably the additional constraint of only one level

dominicm 2020-04-24T21:45:28.366900Z

I'm a browser guy, so I'm thinking of something like js/window.location.href, is that the kind of thing you'd like an alternative to?

dnolen 2020-04-24T21:46:28.368100Z

[FooGlobal$AnalyticsThingy ...]

dnolen 2020-04-24T21:46:42.368500Z

JS globals is also possible

dnolen 2020-04-24T21:46:46.368900Z

[Math ...]

dnolen 2020-04-24T21:47:04.369700Z

I won't cry for js/Math or losing the special casing

thheller 2020-04-24T21:47:18.370200Z

an how do you tell that FooGlobal is an actual global? I mean is every symbol now valid?

thheller 2020-04-24T21:48:11.372200Z

[FooGolbal$AnalyticsThingy ...]? how is the user warned about that typo?

dnolen 2020-04-24T21:48:31.372800Z

for known HTML stuff, Closure can tell us - foreign libs w/o :file is an open JIRA thing

dnolen 2020-04-24T21:48:50.373400Z

the latter give you a way to say you want to use something from somewhere not in the build

lilactown 2020-04-24T21:48:53.373500Z

1. This is sort of moving the goal posts, but I appreciate thinking more generally about this problem 2. I hate the $ as a special delimiter inside of a symbol or string. We have EDN at our disposal; we should be able to craft syntax that represents this

nwjsmith 2020-04-24T21:49:33.374700Z

$ has prior art though...

dnolen 2020-04-24T21:49:39.375Z

exactly

thheller 2020-04-24T21:50:00.375700Z

prior art that is abused for some entirely different purpose

thheller 2020-04-24T21:50:30.376800Z

$ is just how the JVM handles inner class names so its more a JVM thing than it is a clojure thing IMHO

πŸ‘ 2
nwjsmith 2020-04-24T21:51:55.378400Z

But it's how you refer to an inner class, which rhymes with what you want to do here

dnolen 2020-04-24T21:52:12.379Z

also $ is ugly

dnolen 2020-04-24T21:52:17.379200Z

so less likely to clash w/ anything

dnolen 2020-04-24T21:53:17.380300Z

but if people have way better ideas for the delimiter then tell me

dnolen 2020-04-24T21:53:35.380900Z

no ideas about extending the ns form please

thheller 2020-04-24T21:53:53.381200Z

I don't like the idea simply because of the magic character. it does not matter which character it is.

dominicm 2020-04-24T21:54:14.381900Z

Given that . Works as the delimiter already, why something new?

dominicm 2020-04-24T21:55:12.383800Z

"." Is probably a good choice actually... Nobody will use that in js

thheller 2020-04-24T21:55:23.384200Z

. is definitely valid and used in a few npm package names so would lead to ambiguities when trying to figure out which package name the user meant

lilactown 2020-04-24T21:55:59.385500Z

my assumption was that it would make it difficult to resolve a.b.c where b or c could be a namespace or property

dominicm 2020-04-24T21:56:16.385800Z

Really!? Gah. I thought it might particularly not be valid, due to conflict with properties.

thheller 2020-04-24T21:56:19.385900Z

https://www.npmjs.com/package/object.assign and of course there is a object package as well

lilactown 2020-04-24T21:58:22.389Z

I think it’s better to extend the ns form parsing than to add a delimiter. Β―\(ツ)/Β―

Oliver George 2020-04-24T22:03:24.393Z

How about the $ and a reader macro which allows a more familiar require string for node modules to get munged into an unambiguous form

dnolen 2020-04-24T22:08:18.393900Z

@olivergeorge what do you mean, though reader macro is almost automatic no

Oliver George 2020-04-24T22:13:54.395400Z

Rough thought was something like this

(:require [#npm "some/mad.convention"])
or if needed going a step higher to allow for richer syntax
(:require #npm ["@corp/my-lib" :as my-lib :with [default :as my-lib-default]])

dnolen 2020-04-24T22:14:16.396Z

yeah no

Oliver George 2020-04-24T22:14:21.396400Z

fair enough πŸ™‚

dnolen 2020-04-24T22:14:27.396900Z

πŸ™‚

Oliver George 2020-04-24T22:15:23.397700Z

The conflicting syntax & conventions does complicate finding a compatible approach without having "modes" of interpretation... that lead me to a munging wrapper.

Oliver George 2020-04-24T22:15:38.398100Z

I'm not that offended by $ becoming more common

borkdude 2020-04-24T22:20:18.399900Z

> adding more stuff to the ns form that isn't Clojure stuff, that's the hard design constraint I'm not sure if I understand this. trying to fit all the npm lib require stuff into :require ... why not something more dedicated like :npm-require, less confusion overall for tooling as well maybe

thheller 2020-04-24T22:21:44.401100Z

this isn't just about npm. IMHO a string is already clear enough in that the require refers to JS code and not a CLJS namespace

thheller 2020-04-24T22:22:18.401800Z

shadow-cljs had (:js-require ["foo" ...]) for a while but rolling that into :require was way nicer

borkdude 2020-04-24T22:23:10.402400Z

ok

borkdude 2020-04-24T22:24:58.403500Z

are string require names obligated for npm libs btw? I've had one example in #clj-kondo where a user didn't use a string for an npm lib and this resulted in some warnings, because clj-kondo expects you do use a string for npm libs

thheller 2020-04-24T22:25:46.404200Z

in shadow-cljs it is not no. in CLJS you can actually do (:require ["clojure.string" :as str]) I believe which I would consider a bug πŸ˜‰

dpsutton 2020-04-24T22:27:40.404500Z

clojure-lsp does not like the string requires at the moment

thheller 2020-04-24T22:31:52.405Z

CLJS allows any symbol if there is a folder of that name in node_modules. so (:require [react]) is valid if it indexed a node_modules/react before.

borkdude 2020-04-24T22:32:13.405500Z

(ns foo
  (:require
   ["markdown-it" :as md]
   ["markdown-it-texmath" :as md-texmath]
   [com.nextjournal.editor.markdown.todo-lists :as todo-lists]
   [com.nextjournal.editor.markdown.gh-preamble :as gh-preamble]))

(def mdit (.. (md #js{:linkify true :breaks false :html true})
              (use md-texmath)
              (use gh-preamble/Plugin)
              (use todo-lists/Plugin)))
This was the example, but without the string quotes in the requires. This confused clj-kondo because it doesn't expect the alias to be usable as an object, when it's not a JS lib

thheller 2020-04-24T22:32:48.405800Z

shadow-cljs also allows (:require ["./foo.js" :asfoo]) for directly accessing js files from the classpath, so not npm.

thheller 2020-04-24T22:33:21.406100Z

but thats shadow-cljs only and not supported in CLJS (and was rejected there too)

borkdude 2020-04-24T22:34:09.406800Z

aha

dnolen 2020-04-24T22:34:27.407300Z

@borkdude strings are just allowed in general, there's no interesting reason to be more restrictive, use to indicate anything is not a good idea

borkdude 2020-04-24T22:34:30.407500Z

would it be reasonable to ask users to use strings to indicate js libs?

dnolen 2020-04-24T22:34:52.408200Z

the real problem which only tangentially has to do w/ JS is that Clojure notion of symbols is related to what works for Java packages

borkdude 2020-04-24T22:35:05.408700Z

so how can tooling "see" if an alias is a js object or just a CLJS alias?

dnolen 2020-04-24T22:35:12.408900Z

strings widen what characters are allowed in an effective package name

thheller 2020-04-24T22:35:14.409Z

I think so yes. I do recommend that. I hate that node_modules/anything automatically becomes a valid symbol to require

thheller 2020-04-24T22:35:25.409300Z

but that ship has sailed and is not going to change

dnolen 2020-04-24T22:35:36.409700Z

what shadow-cljs does here is just not up for discussing let's stop talking about this in this channel

dnolen 2020-04-24T22:35:48.410100Z

nothing is going to change here

borkdude 2020-04-24T22:37:04.410800Z

I accept that πŸ™‚ But is there a way to distinguish between a JS obj or alias from a tooling perspective (without inspecting the thing at runtime)?

borkdude 2020-04-24T22:37:48.411300Z

if the answer is no, then clj-kondo should treat all aliases as potential js objects

dnolen 2020-04-24T22:40:53.412900Z

@borkdude I think what's happening there is the invokeable ns stuff since some JS libs do that, what's return is a function you have to invoke

dnolen 2020-04-24T22:42:50.414600Z

@borkdude so I think you can't reasonably lint that, we don't do any kind of detection either really

borkdude 2020-04-24T22:44:34.414900Z

thanks

dnolen 2020-04-24T23:11:00.415200Z

(ns foo
  (:require ["@foo/bar$default" :as foo.bar]))

(ns foo
  (:require [global$console :as console]))

(ns foo
  (:require [global$document :as doc]))

(ns foo
  (:require [global$crypto :as crypto :refer [subtle]]))

(ns foo
  (:require [global$CustomModule :refer [bar]]))

dnolen 2020-04-24T23:11:24.415600Z

some typical cases I've observed in pretty much every ClojureScript project that I've worked on

dnolen 2020-04-24T23:12:42.416600Z

the global$foo would resolve to goog.global and be validated against the existing externs (when available)

dnolen 2020-04-24T23:13:23.417500Z

towards the end it's also quite common in a custom JS context (React Native obviously but anything, Ambly, raw JSCore) that you installed a native module at the global level

dnolen 2020-04-24T23:14:18.418100Z

so there's a lot of global patterns here that can be lifted into the ns form

dnolen 2020-04-24T23:14:41.418600Z

in truth that's what the global is, effectively a package, but we don't treat it as such

dnolen 2020-04-24T23:16:24.419600Z

it should in fact probably just be goog.global to avoid a little bit of special handling

dnolen 2020-04-24T23:16:44.419900Z

goog.global$crypto

dnolen 2020-04-24T23:18:14.420900Z

the default stuff is just extra

dnolen 2020-04-24T23:18:58.421600Z

goog.global$Math etc. would provide a discplined way to handle the standard JS builtins without the current hardcoding in the analyzer

dnolen 2020-04-24T23:20:12.422200Z

I suppose for looks in this case goog.global.Math is fine

dnolen 2020-04-24T23:23:17.422500Z

hrm what about : ?

dnolen 2020-04-24T23:23:59.423500Z

(require ["@foo/bar:default"]) and (require foo.bar:default) ?

dnolen 2020-04-24T23:28:39.424600Z

though symbol w/ : is a perfectly valid ns name in Clojure, where $ is likely ugly enough to be uncommon

lilactown 2020-04-24T23:28:51.424800Z

I like it slightly more than $. it feels more aesthetic

dnolen 2020-04-24T23:29:05.425500Z

problem is it's pretty valid

lilactown 2020-04-24T23:29:08.425600Z

I would be super surprised to see either a : or $ in a Clojure ns

dnolen 2020-04-24T23:29:27.426300Z

$ less likely because it appears when munging

dnolen 2020-04-24T23:29:43.426700Z

anything else I wouldn't place any bets

Oliver George 2020-04-24T23:31:38.427600Z

A string form with a space?

lilactown 2020-04-24T23:32:46.428300Z

I wish we could use / but that’s even more likely to show up in js module import

dnolen 2020-04-24T23:32:52.428600Z

yeah no way

dnolen 2020-04-24T23:33:50.429700Z

ok gonna take break, please ruminate on this over the weekend if you're feeling invested πŸ™‚

πŸ‘ 1
richiardiandrea 2020-04-24T23:34:27.430600Z

read the whole thread and I have to say I like the whole idea personally so I give my πŸ‘ I even like the $ cause it is consistent with Clojure

πŸ‘ 1
dnolen 2020-04-24T23:35:11.431100Z

thanks for the feedback!