This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-04
Channels
- # announcements (7)
- # babashka (26)
- # babashka-sci-dev (19)
- # beginners (66)
- # calva (4)
- # clj-kondo (55)
- # cljs-dev (173)
- # cljsrn (17)
- # clojure (86)
- # clojure-art (3)
- # clojure-australia (1)
- # clojure-europe (24)
- # clojure-india (1)
- # clojure-nl (3)
- # clojure-uk (6)
- # clojured (5)
- # clojurescript (39)
- # cursive (8)
- # data-oriented-programming (20)
- # datomic (9)
- # emacs (10)
- # events (1)
- # figwheel-main (16)
- # fulcro (33)
- # gratitude (1)
- # helix (2)
- # hugsql (2)
- # jobs (2)
- # kaocha (4)
- # leiningen (5)
- # lsp (110)
- # malli (1)
- # missionary (17)
- # observability (3)
- # re-frame (10)
- # reagent (1)
- # reitit (7)
- # rewrite-clj (3)
- # shadow-cljs (63)
- # sql (19)
- # tools-build (74)
- # tools-deps (32)
- # transit (1)
- # xtdb (5)
one where the return value is unused and just causes webpack to include the file in the build somehow
import "./some.css"
. this is fine and could be expressed via ns metadata or so without the need to do anything on the compiler side
import SomeImage from "./some.png"
or const SomeImage = require("./some.png")
where SomeImage
will contain the URL to the image for base64 encoded string or whatever. or in case of react-native just an image id.
this is much more problematic since the return value is actually required so the compiler needs to do something. at the very least collect all js/require
calls so they can be transferred to whatever is doing the bundling
the annoying part is that it uses (js/require ...)
or import
in the first place. so the same mechanism as referencing code
my idea for this was creating a cljs.assets/reference
or something macro that'll do the necessary work and then save some metadata in the analyzer data for that ns. after CLJS compilation the various targets could just add whatever code is necessary to wire things together
dunno how this all would actually work since webpack actually allows dynamic requires for this mess, eg. require("./my-images/{foo}.png")
but for the most part people seem to stick to static references
about iteration
in CLJS, re-iterating what I said https://twitter.com/borkdude/status/1489615134297411591:
The iteration function is specifically written for requesting services that have some kind of continuation token to fetch the next page. But in JS requesting such services is nowadays done using promises. Wouldn't it be better if CLJS had something directly based on promises (or callbacks), without having to pull in core.async? Copying iteration
verbatim to CLJS hasn't much value imo, but I could be missing something.
I don’t really have a say, but I do have an opinion! 🙂 While certain constructs don’t necessarily make sense in ClojureScript, there are occasions when people want to use code portably between Clojure and ClojureScript. After all, ClojureScript on Node can do many operations synchronously, and having promise-free alternatives can be useful in such an environment. When such moments arrive, discovering parity between platforms is very welcome.
While some things can be done sync on Node, that's not where JS is moving towards. And for browsers that's definitely not the option that's available.
@U4YGF4NGM it'd be interesting to see if verbatim iteration works with promises as is ...
for CLJS, it would be better if you passed a continuation callback that you called with the next token
There are plans to add a similar thing to core.async, but there are situations where in JS you just want to deal with promises directly
here's some pseudo-code of how an async iteration API might look
(defn fetch-summaries-async
([url]
(fetch-summaries url 0))
([url page]
(iteration-async
(fn [cont page]
(-> (js/fetch (str url "?page=" page))
(.then #(.json %))
;; call `cont` callback with results to collect and continue fetching
;; the next page
(.then cont)))
:kf :next-page
:vf :data
:somef some?)))
> there are situations where in JS you just want to deal with promises directly This is true, but sometimes people don’t want to. They both need support
(defn fetch-summaries-async
([done err url]
(fetch-summaries done err url 0))
([done err url page]
(iteration-async
(fn [cont fail page]
(-> (js/fetch (str url "?page=" page))
(.then #(.json %))
;; call `cont` callback with results to collect and continue fetching
;; the next page
(.then cont fail)))
:kf :next-page
:vf :data
:somef some?
:done done
:error err)))
(defn iteration-promise
[pf & {:keys [kf vf somef]}]
(js/Promise.
(fn [resolve reject]
(iteration-async pf :kf kf :vf vf :somef somef :done resolve :error reject))))
I think that one major difference (other than async ofc) is that you can't rely on lazy seqs to consume each page in a lazy fashion
@thheller what about ^{:js-assets [...] :js-named-assets {"./some.png" some-img}}
? don't care about the dynamic case at all
the named asset doesn't even really need compiler support other than recording for later that you need to generate the ns and assign that value
nothing that causes Cursive and the others to show undeclared var warnings all over the place
(cljs.assets/defasset some-img "./some.png")
creates a deref'able some-img
var usable via [:img {:src @some-img}]
or so
under the hood that derefable looks up the real url or whatever in some js object created by the compiler or so
not in any particular rush about this idea by the way - basically if there's some way we don't have do a compiler pass that would be ideal
I mean whether you collect it from the ns
or the ns :defs
doesn't make much of a difference
but the reader problem on ns metadata kinda means we can only use simple keywords which kinda sucks
in webpack I kinda don't like that you have to tweak the build config if you want to inline vs image url
so (js/require "./some-icon.png")
may return a data url vs a regular url depending on build config
(defasset some-img "./some.png")
results in (def ^{:cljs.assets/reference "class/path/some.png"} some-img (cljs.assets/get "class/path/some.png"))
for example get-asset-data-url
etc. because since CLJS doesn't really care that you have to use Webpack
then CLJS can have placeholders that throw - but shadow could provide them since it manages this stuff
thats why I'm bringing up the classpath. there are use cases where you want to reference stuff from npm packages
much like I have done with this https://shadow-cljs.github.io/docs/UsersGuide.html#classpath-js
path based things use the classpath. ie (ns foo.bar {:asset {:some-img "./some.png"}))
resolves to foo/some.png
on the classpath
if it is a relative path, rewrite it (but this is an implementation detail, users don't care)
classpath is important for library others that want to write say reagent components and include some css and/or images
but there is no ambiguity here. clear rules for this behavior. I hate "look on the classpath first, if not found proceed to npm"
ie. in node (js/require "/foo.js")
actually just looks up /foo.js
on disk. which I replaced with classpath since that is how the jvm works
if somebody says classpath, I know what that means - what you're talking about above is a strange combination
but how do you differentiate then between "look this up on the classpath" vs "look this up in node_modules"
since the classpath stuff needs to do more and node_modules basically nothing since webpack already knows how to find it
well, classpath rules already establish good practice for where stuff goes and naming things
and some library uses the same path and replaces the logo because it came first on the classpath
and skip all this strings meaning somehting - which is probably bad - both of our ideas 🙂
I'm fine with differentiating between classpath and node_modules assets in other ways too
there's an interesting thing which is that defresource
could be JVM friendly way for people to describe assets for the build
I also would like something that is completely CLJ/S only and does not expect to only work with webpack
I see - the shortcut is interesting and natural - but could probably add the sugar later in the pondering process
btw there is prior art for all of this in https://clojureverse.org/t/using-none-code-resources-in-cljs-builds/3745. although I never went further than the inline
macro. it does have the path resolve stuff though.
@quoll re-running tests w/ your latest PR https://github.com/clojure/clojurescript/pull/124
They need to vary a little, e.g. parsing the string form of Long/MAX_VALUE
is beyond the safe integer limit in JS, and it gets rounded
Made a JIRA comment about 3 (likely internal helper symbols) that are currently public that don't appear in clojure.math
Thank you. You’re right with 2 of them… I didn’t think about xor
and get-little-endian
.
I don’t know about IEEE-fmod
though. It’s an implementation of fmod
(and actually returns the same answers as the fmod
found in #include <math.h>
). So even though it’s not exposed publicly in Java, it’s public in other circumstances. I gave this some thought when I wrote it, and actually removed the private flag from it. But I can put it back on.
@quoll Looks like the standard copyright notice needs to be added to the tops of the newly introduced files. (Just look at other files for what it looks like)
@quoll (Perhaps minor thing): It appears that two-to-the-double-scale-up/down
leaves stuff in :advanced
output that appears to be unelidable and calculated at namespace load time. Maybe if they are actually constants they could be replaced with their values. (But maybe they are not VM-independent constants? Dunno.)
No worries. I think it is minor. Wondering if their values of 1.3407807929942597e+154
and 7.458340731200207e-155
can be placed literally in the code, or if those values depend on the VM you are running on... hrm.