This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-24
Channels
- # announcements (8)
- # aws (12)
- # babashka (84)
- # beginners (380)
- # calva (56)
- # clj-kondo (52)
- # cljdoc (4)
- # cljs-dev (327)
- # cljsrn (4)
- # clojure (154)
- # clojure-italy (5)
- # clojure-nl (3)
- # clojure-uk (21)
- # clojurescript (52)
- # conjure (133)
- # cursive (64)
- # datomic (33)
- # emacs (22)
- # fulcro (35)
- # graalvm (24)
- # graphql (1)
- # kaocha (1)
- # leiningen (1)
- # off-topic (24)
- # onyx (2)
- # pathom (10)
- # re-frame (3)
- # reagent (3)
- # reitit (3)
- # shadow-cljs (48)
- # spacemacs (12)
- # tools-deps (98)
- # xtdb (7)
@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)
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
?
Why not, it's possible. It's a way to deal with it. So the :default
keyword from shadow-cljs is deprecated?
no, it isn't. just makes libs shadow-cljs only which I lib authors should avoid (IMHO)
Ok, if you advice to avoid it, so if cljdoc doesn't support this keyword, it's pretty reasonable, no?
Yes, I think supporting :default would be outside the scope for cljdoc since the library would be only usable from shadow anyways
one alternative for the :default
thing just always do the rename bit for Node.js libs?
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
what do you mean by automatic? I mean how would you know whether a react-native
package has a default
export or not?
right we would need to add that metadata, I thought our node_modules
processing looked at exports
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
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
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)
@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
@roman01la yeah that was definitely one of the patches clj-nil
not considered a number type anymore
Am I doing something wrong here?
clj -Sdeps '{org.clojure/clojurescript {:git/url "" :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.
I think that was my patch
you're missing the :deps level
clj -Sdeps '{:deps {org.clojure/clojurescript ....
right clj -Sdeps '{:deps {org.clojure/clojurescript {:git/url "
ah I see, thanks
@roman01la I'm going to revert your patch
@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?
not to my immediate knowledge
there's a date sort somewhere
2009/05/17 17:58:44
a format like that might work to set an explicit time for the postlet me try it
that seems to sort and appear correctly for me if I use 2020-04-24 23:59:59
but may just be coincidence, not totally sure
do you want me to push current site or wait?
just ping me
@alexmiller fire away
@alexmiller just added some missing updates - let me know when it's ready and I will post updates to various channels
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
@dnolen sorry, was heads down on other stuff, will push site
@alexmiller minor typo, another push whenever you can
@thheller I don't really understand your concerns about handling exports when stuff like this exists https://github.com/rollup/plugins?
given the years of prior art - this doesn't seem problematic to me, your comments so far seem to be ignoring this?
@alexmiller another bump on the site, typo in the webpack guide
button pushed
@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
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}
I understand you don't want to add stuff to the ns form and I'm fine with that ... don't do it then
but adding compiler magic or adding third party tools does not address this problem in any way whatsoever
how do you mirror import * as thing from "foo"
then if :as
is already "used for default"?
it's imports the default under one name, then all other exported symbols into a different bag called everything
all I'm looking for is being able to express all the variants of import
that the ESM spec has
so host-interop doesn't matter? I mean we have :refer-macros
and other stuff clojure doesn't have?
give me a full example please. not really sure what you mean? as a separate require?
I made a translation table here https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages
see ES6 Import to CLJS Require
so that people can look at a JS example of how to use a certain library
anyways the end result is something that would get the same result w/o futzing w/ the ns form
I cannot make a compelling argument if you have already decided that you are not going to add :default
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
foo$default
and "foo$default"
semantically would let us get at the default export as a namespace-y thing
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.
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?
@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.
my personal feelings right now is that it would behoove CLJS to pave the path to using standard JS
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
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
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
I'd be careful with that statement. It is still not "final" on how CommonJS <> ESM is ultimately going to work
so import React from "react"
is actually correct as long as react
only ships CJS code
but since no browser even supports that option and likely never will its always going to stay a bundler thing
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)
probably because they really want to ship ESM but canβt because the ecosystem is still so choatic
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
like this conditional require of the minified bundle https://unpkg.com/[email protected]/index.js
you cannot do this with ESM .. you need import maps for that ... but that is yet another unfinished spec
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 π
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.
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
you can do that today. just can't also mix in some random npm commonjs code (eg. react)
if you have all ESM it does not no. the interop/mix is the issue. all ESM or all CJS is totally fine.
the actual point Iβm circling around is that I agree with adding a :default
import π
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}
I'm a little out of touch with esm, if you do import x from "y"
does x.z make sense for all things?
Its usually a single object like a class or so. haven't seen a case where that be an actual "namespace"
which I floated around before which is that foo$default
might not need to be specific to ES6
only in the cases where CommonJS is actually imported that way .. so import React from "react"
and React.createElement
so that's another to weigh, Foo$Bar
could be generic pattern rather hard coded to default
problem
@lilactown yes all these standard apis could be required as namespaces
@lilactown (:import ...)
is really just a hack for GCL
@lilactown I don't think Foo$Bar
pattern can help much with that
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
how will it work with imports that are strings? "@corp/my-lib$default"
seems gross to my eyes
and I guess, IMO it would be better for external analysis to not have to parse strings / symbols
so we are not modifiying the ns because :default
is "new" but we are adding a whole bunch of magic for accessing nested properties?
this isn't a very challenging change we already have everything to return whatever from a resolve
I mean adding new functionality to ns
. not talking about implementation at all, I know that is trivial.
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
I think regular JS interop is fine for this don't know why the ns/resolve would need gain that functionality
don't even want to think about an npm package that has an actual $
in its name. I'm sure there exists one π
@lilactown I'm already talking about bigger problem now
I am tracking your thoughts I think. I disagree with the ergonomics of using a special $
delimiter
@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
?
(ns
;; 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]]))
the difference between :with
and :refer
/ :rename
is that the symbol would be treated as a namespace, not a value
@lilactown noooooooooooooooo π
more interested in feedback about a problem in literally all ClojureScript codebases right now
tons of libraries / apps right now accessing properties which are just namespaces, global which are just namespaces
I'm not asking about node_modules. I used that as an example of how the actual syntax is supposed to look
it would only work on the ns identifier itself nowhere else, and probably the additional constraint of only one level
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?
an how do you tell that FooGlobal
is an actual global? I mean is every symbol now valid?
for known HTML stuff, Closure can tell us - foreign libs w/o :file is an open JIRA thing
the latter give you a way to say you want to use something from somewhere not in the build
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
$
is just how the JVM handles inner class names so its more a JVM thing than it is a clojure thing IMHO
But it's how you refer to an inner class, which rhymes with what you want to do here
I don't like the idea simply because of the magic character. it does not matter which character it is.
.
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
my assumption was that it would make it difficult to resolve a.b.c
where b
or c
could be a namespace or property
Really!? Gah. I thought it might particularly not be valid, due to conflict with properties.
https://www.npmjs.com/package/object.assign and of course there is a object
package as well
I think itβs better to extend the ns form parsing than to add a delimiter. Β―\(γ)/Β―
How about the $ and a reader macro which allows a more familiar require string for node modules to get munged into an unambiguous form
@olivergeorge what do you mean, though reader macro is almost automatic no
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]])
fair enough π
The conflicting syntax & conventions does complicate finding a compatible approach without having "modes" of interpretation... that lead me to a munging wrapper.
I'm not that offended by $ becoming more common
> 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
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
shadow-cljs had (:js-require ["foo" ...])
for a while but rolling that into :require
was way nicer
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
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.
shadow-cljs also allows (:require ["./foo.js" :asfoo])
for directly accessing js files from the classpath, so not npm.
I think so yes. I do recommend that. I hate that node_modules/anything
automatically becomes a valid symbol to require
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 π
(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@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
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
what shadow-cljs does here is just not up for discussing let's stop talking about this in this channel
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)?
if the answer is no, then clj-kondo should treat all aliases as potential js objects
@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
@borkdude so I think you can't reasonably lint that, we don't do any kind of detection either really
(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]]))
some typical cases I've observed in pretty much every ClojureScript project that I've worked on
the global$foo
would resolve to goog.global
and be validated against the existing externs (when available)
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
in truth that's what the global is, effectively a package, but we don't treat it as such
it should in fact probably just be goog.global
to avoid a little bit of special handling
goog.global$Math
etc. would provide a discplined way to handle the standard JS builtins without the current hardcoding in the analyzer
though symbol w/ :
is a perfectly valid ns name in Clojure, where $
is likely ugly enough to be uncommon
A string form with a space?
ok gonna take break, please ruminate on this over the weekend if you're feeling invested π
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