This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-10-31
Channels
- # announcements (5)
- # babashka (105)
- # beginners (92)
- # calva (77)
- # cider (17)
- # cljdoc (8)
- # cljs-dev (8)
- # cljsrn (8)
- # clojure (272)
- # clojure-dev (25)
- # clojure-europe (5)
- # clojure-italy (6)
- # clojure-nl (7)
- # clojure-norway (3)
- # clojure-uk (108)
- # clojurescript (326)
- # code-reviews (4)
- # cursive (6)
- # datomic (37)
- # duct (5)
- # emacs (14)
- # fulcro (23)
- # graphql (1)
- # juxt (1)
- # kaocha (2)
- # leiningen (10)
- # malli (9)
- # music (1)
- # nrepl (12)
- # pathom (21)
- # pedestal (2)
- # planck (4)
- # quil (3)
- # reitit (29)
- # rewrite-clj (10)
- # shadow-cljs (82)
- # spacemacs (29)
- # sql (6)
- # tools-deps (19)
I’m curious if any other folks have ended up writing a ‘hook’ as a macro…
(it’s not gratuitous, load-css!
uses shadow.resource/inline
which requires a literal string argument, otherwise I’d find this very surprising)
makes sense, took me by suprise at first but pretty clever
Heya, I’ve got a question about transit and cljs - how to reduce encoded size while keeping the ui repsonsive https://ask.clojure.org/index.php/8795/how-can-reduce-the-size-transit-encoded-data-clojurescript if anyone has ideas, would be much appreciated!
What's that 6mb limit in Android? Is it async storage?
yeah. Apparently you can increase it via gradle properties, but I’m using expo and don’t want to eject at the moment
Would be an option for you to use sqlite instead? Of whatever dB there's on Android
This is only tangentially related, but I've encountered what I think is a bug in nginx, where JSON proxied from my app gets truncated at 3MB.
could vx be made to work with https://github.com/Niekes/d3-3d or equiv?
Vx/d3 is on a different level to vega. Sometimes you've got very specific designs for a graph, and d3 is the better tool
There's also this: https://github.com/gadfly361/rid3 which I've only played with briefly
I'm new to Clojure[Script] and I can't figure out this error message.
I started a new project using `lein new chestnut calculator -- --vanilla
https://github.com/plexus/chestnut
I added cljsjs/react
as a requirement and updated my core.cljs
file.
Here is the diff
diff --git a/project.clj b/project.clj
index 0b1f23a..df9dac9 100644
--- a/project.clj
+++ b/project.clj
@@ -16,7 +16,9 @@
[com.stuartsierra/component "0.3.2"]
[org.danielsz/system "0.4.1"]
[org.clojure/tools.namespace "0.2.11"]
- [compojure "1.6.1"]]
+ [compojure "1.6.1"]
+ [cljsjs/react "15.1.0-0"]
+ [cljsjs/react-dom "15.1.0-0"]]
:plugins [[lein-cljsbuild "1.1.7"]
[lein-environ "1.1.0"]]
diff --git a/src/cljs/calculator1/core.cljs b/src/cljs/calculator1/core.cljs
index a2ce140..ec4ac84 100644
--- a/src/cljs/calculator1/core.cljs
+++ b/src/cljs/calculator1/core.cljs
@@ -1,4 +1,6 @@
-(ns calculator1.core)
+(ns calculator1.core
+ (:require [cljsjs/react]
+ [cljsjs/react-dom]))
(enable-console-print!)
And when I run lein figwheel
, I get the following error.
Failed to compile build :app from ["src/cljs" "src/cljc" "dev"] in 0.641 seconds.
---- Could not Analyze src/cljs/calculator1/core.cljs ----
No such namespace: cljsjs/react, could not locate cljsjs_SLASH_react.cljs, cljsjs_SLASH_react.cljc, or JavaScript source providing "react" (Please check that namespaces with dashes use underscores in the ClojureScript file name)
I have confirmed cljsjs/react
is in ~/.m2/repository/
. So it's getting picked up as a dependency. Where can I find documentation around how lein/figwheel search for JavaScript dependencies while compiling?Sorry, that was a copy/paste error. I created the calculator1
project and then copied over the smallest amount of code to reproduce the issue. The error is not related to that. I corrected the name and get the same issue.
Son of a.... that's even what the damn error message says. I had it in my head that the error message was about directory paths and not the require statement.
Hi, is there a way to use async
and await
with Clojurescript ?
@benoit.caccinolo no but it's really not needed
ok thanks, I’ll have to check core.async
so 🙂
you can write a little helper macro like <p!
over core.async
<!
that throws on Promise reject
thx I’ll check this
if you’re not actively using core.async, a lighter-weight solution might be to use a smaller library that deals just with JS promises, like kitchen-async: https://github.com/athos/kitchen-async
that’s what I’m using rigth now but the nestings with p/then
is annoying
you’re right, that’s not a good phrase to use. “If you don’t need/want the abstraction cost that core.async brings,” is what I meant in this case
sorry dnolen, I’m not trying to be obtuse. I think there is a jump from “use promises but with async/await” and “introduce channels” which are fundamentally different constructs. at some point a person using core.async in a code base will need to not only know promises, but also channels/CSP and core.async’s implementation of them.
there is a vague notion of performance that thheller is talking about but that’s lower on my feelings about this than the above
I would like to be able to write this const matches = await page.evaluate(utils.extractMatchesDataFromPage);
no nesting 🙂
ah ah cool.
I've never been in scenario a where I could detect any type of meaningful overhead in runtime performance
that's possible but far as I know when I look at the code gen for JS async/await
it didn't look meaningfully different to me
but core.async still generates a lot more code than the equiv transpiled async/await stuff
a whole lot of use cases can use native async/await .. that is the point. you can't just look at the browser anymore
to be honest I haven't looked at this in a while - but when I compared this back when we developed core.async
and optimized it
the differences didn't seem meaningful to me, 2X maybe - then factor in advanced compilation etc.
well it is different nowadays ... async/await beats out hand-written promise code in pretty much all cases
I said this in a thread above… I also think that there is a greater cost to adding core.async to a codebase than performance (if that’s the case). adding core.async to a code base requires one to now think in channels, and understand core.async and it’s machinery, as well as how to interop with promises. it’s just more stuff, vs. promises with async/await syntax.
I don't know the last time I worked on a project where the code size was coming from core.aysnc
usage
I can show you code right now in the core.async library itself that generates massive amounts of code
but it isn't so much about the code size alone. chrome devtools support is just better for promises
currently we're using core.async in multiple situations for exactly what was being discussed
I do use core.async myself all the time ... I mostly agree with you. just saying that there is "no difference" is what bothered me. there definitely is a difference nowadays
it works well enough and in the typical HTTP fetch I/O situation debugging isn't that interesting
all I meant what that if you can't depend on the presence of async/await then you're going to have to codegen
to me it's just as misleading to state that core.async
is somehow not pretty well suited for dealing w/ JS promises
it works great if you know how to build the <p!
and how to turn a core.async channel into a promise
yeah I’m thinking about this from the perspective of someone who hasn’t used core.async before
I mean, that's true of someone who hasn't used async/await as well. There's a learning curve to both models
telling someone to “add core.async and channels” is like… okay now I have 2 problems lol
I'm also not sure the performance of core.async is worse than native async/await. Async/await beats hand written promises. But core.async isn't hand written promises.
I was looking into the async/await case a week or so ago. Mostly I wanted to use a third party lib that gave me promises.
I tried hard to figure out what the "easy" way of using core.async
was, and I could not find any good example.
I ended up using Promesa
for a while. Then I removed Promesa
and just used threaded (.then ...)
.
I really would have loved to use core.async
in a idiomatic clojure way but the information just wasn't available. And since I was making code that novices would have to understand, that was a deal breaker.
IME the times I’ve needed channels while developing modern front-end apps has been pretty small when using React. most of the places that we introduced core.async in the past, I’ve later gone back and refactored to use promises and it was an improvement. that could have been our misunderstanding of how and when to leverage core.async in the past, but that’s kind of my point.
promesa’s async/await had some bugs and they may have weighed the cost of supporting it and decided to drop it
IMHO is core.async
is a great way to interact with promises there really needs to be a official guide and example for it.
you just cannot avoid promises when using libs
Their commit message said something along they didn't find it useful given the added complexity of maintaining it.
w/ the above macro+helper you can literally write exactly what JS async/await examples show
I don't question it's possible. I assert that, if I want to show a novice how to use core.async
with promises, I cannot give them a good resource.
https://clojureverse.org/t/async-generator-functions-in-cljs-requesting-feedback/2262/8?u=thheller
does that exit? promise/await
?
It might sound weird but I don't understand what that does, nor how to use it. If it's the right thing to use, it's very daunting. I couldn't come up with it for a while after learning cljs.
The https://github.com/athos/kitchen-async puppeteer example is great and makes sense. I can show that to someone and they know how to use it.
If there was a similar example for core.async
in http://clojurescript.org/ that would be a nobrainer.
this is such a regular reoccuring topic that I agree we need a post + maybe just standardizing into cljs.core.async
and I assert that, telling someone that wants to deal with promises easier to introduce core.async
into their app is not the best idea.
It’s easy for us to tell other people to do that because we already paid the cost to learn CSP and core.async
. in general, I don’t want it in my code now. But i’m also happy with threading .then
to avoid it
you can turn that argument the other way around and it goes something like "you can learn start using core.async for promises and understand it better later".
I think stating a standard way to solve a problem doesn't mean you can't ignore it and do it your own way
I think it's more effective to say do it this way - then send them off to make a bunch of decisions
they can always make different decisions later once they know at least one way to do it that reasonably straighforward
I have to admit not doing a lot of front end. So I'm curious, is async/await really nicer then threaded .then
? I feel core.async is at it's most useful when the amount of concurrency is high. But my impression is most situation for async/await are very simple, like, I wish this operation was synchronous, I just want to do a then b then c.
personally I don't know if it's nicer. I wanted to use it because it sounded more idiomatic. But I ended up not knowing because I couldn't find the information.
yes, the "one way to do it" is the important bit
if that macro is a reasonable way to do it then it would be better to have it in core.async directly too
having a "using promises" section that starts with defining a macro is a bit daunting for a novice
IMO telling people, “thread .then
/ .catch
is the default, we don’t have native async/await. If you want to take on more complex async programming in your apps, use core.async
” would be better than suggesting core.async
without qualification to ClojureScript beginners.
I don't really agree w/ that because all this talk is about JS-centric perspectives
I’m getting more entrenched in this as I talk about it so I might pull out of this convo lol. I feel like it’s if someone were to tell beginners to use RxJS to handle promises in their app.
Is this something that exists currently? I can't seem to find it in http://cljs.github.io/api/ or references to it on google
Clojure is different because you don’t use core.async for one-shot deferred values like we’re telling people to use core.async for in CLJS
if someone said they wanted to do an HTTP request in Clojure, I’d tell them to use either a blocking call or a future. I’d only pull in core.async if they had something that would actually leverage channels’ multiple-values-over-time and that wasn’t IO heavy in the channel execution.
again, looking at this from the viewpoint of someone who isn’t using core.async and wants to make a bunch of HTTP requests. they don’t need or want core.async. they want a future. same thing in CLJS: they want an easier way to write promises, not to learn core.async.
I haven't found channels that useful in UI programming, because usually you want to visualize all of the state. For example, in Pike's 3 request /w timeout example, you may want to show the state of each of those requests on the screen, in which case app-state is coordinating stuff, no channel seems that helpful.
That's it? doesn't really seem that bad. Not like I need to become a deep guru of CSP multi-channel architecture. (re: core.async one-shot HTTP req)
in CLJS it would be:
(go (let [result (p->c (http/get ""))]
(println (<! result))))
but the cost isn’t in the code you write, but now at some point you will need to learn about how core.async works. e.g. how to handle errors, the syntax rules for go
and <!
, and deal with bugsimo getting used to using core.async rather than using futures makes sense, because then you’ll be more familiar with the powerful tool when you need it, rather than investing in learning the intricasies of future which is comparatively less powerful. I see the point that it’s extra to learn though
@lilactown - the p->c is required?
Well https://github.com/r0man/cljs-http returns a channel to start with
yes, my initial example was clojure, as that was what david was talking about saying he does all the time in clojure
aaaanyway. core.async rocks. imo learn it, use it, love it. in a crazy pervasively asynchronous world like inside javascript I couldn’t imagine getting along without it
some of this surprised me. Clojure prides itself on having a strong host interop and being a hosted language. So a shyness regarding js promises feels a bit counter to the ideal of embracing the host
i don't want to weigh in on either side. this isn't a problem i have a strong opinion on. But defaulting to async over interop with promises kinda surprised me is all i'm saying
I get where dnolen is coming from from the viewpoint of a maintainer. adding support for JS async / await does not have immediately obvious benefits. IMO it’s in the pedagogy, and flattening the abstractions we have to layer on top of our applications, in order to meet the standards that people set for languages today, that make me feel like it’s worthwhile. but it is a non trivial amount of work AFAICT to get async / await to work with today’s CLJS compiler
the first problem is that people are coming from JS, which sways to the whims of whomever is loudest frequently, and they go “where’s my async / await? I expect modern languages to have async / await”
@dnolen I can give my concrete example since it's very fresh in my mind. I'll put it in a post to not spam the channel.
maybe, but knowing that also doesn't help me
now I have a macro I don't understand, core.async that I don't understand, and a promise that I still need to use
I totally imagine there's a really nice way to do it
but I do not know it
i think for someone that hasn’t worked with async/await, it’s the same learning curve just to start with core.async… there are also people who have worked with core.async in clj and find it easier to work with in cljs because it uses the same abstractions. just my personal experience.
also not every modern language has async/await, if you’re coming from go for example it would be easier to work with core.async
honestly I would expect that if someone hasn’t worked with async / await, chaining .then
is probably just as good.
if you have used core.async, like core.async and want to use it, then you can!
if you have used async / await, like async / await and want to use it, then…?
telling people to use core.async is IMO not a good plan if what they want is to do “normal JS stuff”
As a Clojure leaning dev (meaning minimal cljs, mostly Java Clojure) I think the issue is that everything has to be thought of from the viewpoint of Clojure the language and its family
It's an opinionated language with paradigms choices. So the question has to be, what's best for working with async APIs?
Yes, but it doesn't include all of Java's concurrency primitives. So I can only assume Rich was selective
Worth mentioning that if you do CLJS you can conceivable only learn promise interop without understanding core.async
but the reverse isn't true.
even if you use core.async
with promises you have to understand promises
and if you come from JS to CLJS the answer to using async/await
shouldn't be "don't use it, use .then instead"
even if it's better in some ways it just sounds backwards
cljs has macros for syntax, surely it should be able to make that work well out of the box
await was just macro-like structures until recently
until last year or so it was uncommon to have native await support
ts/babel and all those simply downleveled it to a convoluted promise base structure
the problem I have with telling people to use core.async
is you now have to understand promises and channels
I think that a macro can go a long ways, but there was a thread awhile back where jmlsf went into the deficiencies of macros for this (specifically the deficiencies in promesa, but some of this is inherent to macros): https://clojureverse.org/t/async-generator-functions-in-cljs-requesting-feedback/2262/22
the rxjs example that was mentioned (by you I think?) is very apt
Angular forces usage of RxJS in the framework. This was roughly 4 years ago.
On polls about topics people want to see in the main angular conferences, beginner RxJS is still one of the top 5 topics. Almost no one does it right. Many conference talks are still about beginner RxJS.
One of the most common usages of RxJS is to get an observable and call .toPromise()
on it.
I hopped on the RxJS hype train right around then, and eventually just got fed up with it because I almost never needed the power it was giving me, while constantly having to fight its inherent complexity
I feel the same way with core.async / CSP. I think it’s better than RxJS for many cases, but most people just need a way to do some flow of async IO that is much easier to do with promises than something that makes operating over multiple values over time first class.
I ended up using a lot of rxjs and it definitely made me realize how a lot of thing were better with rxjs
but the sheer amount of work that it takes to do it, and the way it absolutely massacres stack traces... make it onerous
I think the comparison is a bit unfair. core.async is way smaller and easier to learn than rxjs imo
have y’all read david’s blog posts on core.async? they’re really good. the first one is “Communicating Sequential Processes” https://swannodette.github.io/
@filipematossilva it is not possible to implement async/await with macros: https://observablehq.com/@shaunlebron/proposal-generators-and-async-functions-in-clojurescript
I was under the impression it was possible with the core.async based macro that David Nolen posted here around 1h ago
I guess I have some reading to do, this one and the one lilactown mentioned just now
Ok, the article speaks about emitting async/await js code and I thought you mean that. You can probably implement something with similar semantic as async/await, on top of core.async, raw promises or something else.
the benefits of emitting async/await JS code is wayyyyy better stack traces, and tooling support in devtools
but for me, implementing core.async on top of native async/await would be enough for better dev experience
the IIFE problem in shaun’s post is one that is annoying me right now for other reasons
I guess, today it would need parts implemented in raw js since cljs does not emit async/await
funnily, I think this might be able to be ameliorated by adopting another modern JS feature in our output: let
/ const
Ah yeah native async/await is a different beast. But transitioning to emitting native async/await is usually a tradeoff with support for legacy runtimes.
even today if you want to use full ES2015 it is advisable to also ship a ES5 build for both frontend apps and node libs
the CLJS compiler emits a lot of IIFEs in order to guard against bindings being hoisted and clobbering things
I hadn't considered the downleveling in GCC. Yes you are right.
which makes it much nicer for all of us, because then we can tune our JS bundles to the specific platforms we need to support
it's a good strategy overall, emit at the latest language target supported by the downleveler, then allow the downleveler to do it's thing
actually, doesn't this allow emitting async/await?
I found it in the link @U08E3BBST put up at the start of the thread
sort of, the idea of my post was that cljs cannot generate js code containing async/await, not that you cannot implement something which looks like it
You would have to first implement an async/await macro in my opinion. Make its usage ubiquitous. Port it to Clojure as well. And then demonstrate that the macro should have special handling in the cljs compiler so it is optimized further into native async/await JS code. For that, you'd need to show that the work required is worth getting nicer stack traces and maybe slight performance gains.
I'm not sure the compiler work would be worth the effort tbh. Given the small number of contributors and everything else they could work on instead. But still.
I share this opinion. It's somehow ironical to have so much requests for implementing async
/`await` at the compiler level, and at the same time nobody willing to write and maintain a library to do that in macro space.
I totally understand the arguments about clean stacktraces and hypothetical performance gains, but keeping a sound language design is a valuable target as well.
TBH whenever that post comes up I always am more interested in generators than async
Well speaking about that, leonel has a very nice coroutine lib that let's you implement imperative generators
I’m less interested in imperative generators as a concept and more interested about potentially being able to interop with JS iterators/generators
That said, I also want to point out you can do functional generators as well, using Clojure's lazy iterators as explained here https://www.rubberducking.com/2018/04/overview-of-clojurescript-110-features.html?m=1#iterators-and-lazy-sequences
but interesting part is being able to use JS generator functions, or hand CLJS built iterators/generators to JS
sure, but if we’re talking about implementing the concept, I want to be able to leverage the platform
Hum... I'm just trying to think here. If they're just an object of a particular interface, it should be possible to create them in cljs no?
That's a good use case though. I do understand interop challenges can be annoying. I'm still waiting for interop with Java functional interfaces and streams. But like leonel said, I think long Hammock time is needed to also make sure Clojure maintain consistent good language design. Those things can be at odds
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator
I think that what I want and what leonel wants are a bit at odds. I don’t think they have to be contrary, but I think that we are likely to disagree about certain things
leonel has done some amazing work with missionary and cloroutine to create some beautiful abstractions and the capability to implement a lot of these concepts we’re talking about in a cross-platform, Clojure-first way
however, there are risks with that. in the same way that core.async maintenance has fallen to the wayside, those projects are currently a one-person shop.
meanwhile, every browser that I want to support today has first-class support for generators and async/await. and my applications will continue to get faster and more support as browsers improve upon those features
I am perfectly happy using different abstractions, libraries, etc. between Clojure (threads/core.async/missionary/etc.) and ClojureScript (promises/generators/etc.) if it means I get best-in-class features and support
so it’s frustrating when people say, “we can just build async/await ourselves! we can create our imperative generators! etc.” when like, I might have to take over maintenance of that code if my app depends on it and life happens to the author. or I have to build it from scratch and support it myself to suit my use case… when if I could emit certain JS code I would get it “for free”
I understand that we want to keep the core Clojure language tight and be careful about introducing things willy-nilly. but what I really want is an escape hatch to be able to leverage these new platform syntax features which get better first-class support than what we can provide in Clojure. that’s my thesis.
But I think I disagree with the conclusion. The compiler team is also a one man show pretty much
I agree, which is why I’ve stated above this thread that I empathize with dnolen’s position
Which may get stale, might not keep up with the pace of JS, might make it harder to implement future Clojure behavior etc.
I’m willing to accept that “add async/await/function*/yield to CLJS” is not the right move. so as I’m thinking more, what I really want is the ability to extend the CLJS compiler to emit these new features
I understand at a high level this would require a significant rework of the compiler. I think that it will save us all a lot of time and energy arguing over this crap as the JS spec continues to grow
I’m not demanding these changes. I think it’s OK to say “yes that’s a good idea, no we can’t do it”
Ya, a lot of this is us Clojurian are required to get by with little resources. Luckily, it seems applying the 80/20 rule generally has allowed us to keep up with everyone else. And the number of smart people in this community even meant often we were ahead.
I like the idea of an escape hatch. In Java land, you can actually write code that generates Java byte code or java source code. I've done both of those in the past. It does allow an "escape" hatch in that sense. You can also just mix and match java files with clojure files, and the one class per file and everything being a file in Java does mean it is pretty clean doing so. I'm not sure about CLJS
In JS, you don't really have each function or each object be its own file. Maybe having a way to embed JS in CLJS would be a good to have.
in certain ways, JS is more free and loose. I’ve written ClojureScript code to generate JS, but it was not concerned with code size or advanced compilations or interoping with the rest of the CLJS compile toolchain in any way
I don't think the size is the important part of the comparison. The promise/rxjs situation was (is) one where people that know promises feel they have to learn and use something else that looks more complicated to do things they found pretty easy to do with promises. Even if it ends up being better, it's still an overhead. And overheads for beginners are very costly. Kinda like the syntax error problem described in https://elm-lang.org/news/the-syntax-cliff.
pro tip: for peeps using devcards and React/Reagent, use an error boundary around the component you’re iterating on to avoid blowing up your whole page when you accidentally throw an error inside your component
example in Reagent:
(defn- err-boundary
[& children]
(let [err-state (r/atom nil)]
(r/create-class
{:display-name "ErrBoundary"
:component-did-catch (fn [err info]
(reset! err-state [err info]))
:reagent-render (fn [& children]
(if (nil? @err-state)
(into [:<>] children)
(let [[_ info] @err-state]
[:pre [:code (pr-str info)]])))})))
(defn my-component []
(throw (js/Error. "Oops! 👻")))
(dc/defcard-rg
my-component-card
[err-boundary
[my-component]])
oh hey that's smart
hey all, im trying to rerun a cljs app that was built 5 years ago, and i'm coming across this error: Uncaught Error: Undefined nameToPath for goog.math.Integer
anyone have suggestions for how id go about debugging that? seems like cljs is having trouble requiring the goog.math module
my wild guess would be that goog.math used to be included by default and your code relied on it
try to require it somewhere at the top level or near the namespace which is raising the issue
did it use to? i can't find anywhere in the code where im directly using goog.math, maybe its a problem with one of the outdated libs im using
I don’t know, goog.math.Integer is still a thing: https://github.com/google/closure-library/blob/master/closure/goog/math/integer.js
yea im tryna help someone remote debug who's not that familiar with clojure. ok but i guess ill tell him to get devtools set up
by devtools i think he means just the js console. not really something to set up? unless i'm mistaken
Uncaught Error: Undefined nameToPath for goog.math.Integer
at visitNode (base.js:739)
at visitNode (base.js:737)
at visitNode (base.js:737)
at Object.goog.writeScripts_ (base.js:753)
at Object.goog.require (base.js:459)
at (index):38
visitNode @ base.js:739
visitNode @ base.js:737
visitNode @ base.js:737
goog.writeScripts_ @ base.js:753
goog.require @ base.js:459
(anonymous) @ (index):38