This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-06
Channels
- # beginners (49)
- # calva (12)
- # cider (5)
- # cljdoc (4)
- # clojure (51)
- # clojure-dev (1)
- # clojure-europe (16)
- # clojurescript (56)
- # conjure (2)
- # copenhagen-clojurians (1)
- # core-async (4)
- # data-science (4)
- # docker (1)
- # emacs (4)
- # gratitude (1)
- # malli (2)
- # meander (2)
- # missionary (7)
- # off-topic (23)
- # pedestal (3)
- # polylith (6)
- # shadow-cljs (28)
- # spacemacs (1)
- # sql (9)
- # transit (8)
Hi, I wonder to know what's the more idiomatic way to import npm library when it default exports a JS object:
module.exports = {
rainbow: (str, speed) => animateString(str, effects.rainbow, 15, speed),
pulse: (str, speed) => animateString(str, effects.pulse, 16, speed),
glitch: (str, speed) => animateString(str, effects.glitch, 55, speed),
};
Currently I doing something like
(ns my-ns
(:require ["chalk-animation$default" :as chalk-animation]
[goog.object :as gobj]))
(def rainbow (gobj/get chalk-animation "rainbow")
(js/console.log (rainbow "My wonderful text"))
:refer
of particular names should work. Like :refer [rainbow]
.
Or (def rainbow (.-rainbow chalk-animation))
. No ^js
needed in this case - well, at least in the case of shadow-cljs, no clue about others.
Thanks @p-himik, will try!
Currently playing with Nbb, already trying the second one and it doesn't works. I get undefined
.
Works perfectly with :refer [rainbox]
.
This is what I try first but don't know why I had initially no success.
Maybe previously forget to append $default
or something like that.
Thanks again.
Oh, that's interesting. @U04V15CAJ any clue why that might be? Couldn't find anything in the issues and documentation.
Seems like module.exports = {...}
does create a default export in nbb
, I didn't expect that.
Anyway, you can do this:
(require '["chalk-animation$default" :as ca])
ca/rainbow ;; Can use like this.
(.-rainbow ca) ;; Or like this.
And in a raw Node-based REPL, $default
doesn't work, as I would expect:
=> (require '["chalk-animation$default" :as dd])
nil
=> dd
nil
But using it as is, without $default
, works just fine:
=> (require '["chalk-animation" :as ca])
nil
=> ca
#js {:rainbow #object[rainbow], :pulse #object[pulse], :glitch #object[glitch], :radar #object[radar], :neon #object[neon], :karaoke #object[karaoke]}
=> ca/rainbow
#object[rainbow]
Yes, nbb loads dependencies via js/import
which is dynamic import implementation for dealing with ES modules in Node.
This is why it's different than in a "normal" Node.js CLJS REPL since CLJS approaches Node deps as common JS. You cannot even load ES modules in a normal CLJS REPL I believe
If you would use :target :esm
with shadow cljs you would have to load the deps the exact same way as with nbb.
Thanks @U04V15CAJ for all these interesting informations. Yes, problem solved! 👍
Interesting conversation. I had been struggling with same. A normal [react-native-contacts :as contacts]
works for me.
Dunno what is that.
In js it is done like this:
import Contacts from 'react-native-contacts';
neither work:
1st gives undefined
2nd gives [ReferenceError: Can't find variable: Contacts]
I am using krell for react-native
(defn is-ok? [err]
(= :ok (first err)))
(def is-err?
(complement is-ok?))
(comment
(is-ok?) ;; I get the expected wrong number of args passed error
(is-err?)) ;; true
In Clojure, calling something like `is-err?` with the wrong number of args to the inner complemented fn gives me the expected error but it doesn't seem to be the case in CLJS. I assume this is a JS quirk but was curious on what is happening here.It is indeed the issue of JS. In that case, you get err
bound to undefined
.
One of the few reasons why I don't like complement
and other similar higher-order functions, like partial
and comp
(except when used for transducers).
It's not that much more code to just use this:
(defn is-err? [err]
(not (is-ok? err)))
When you say you don't like other higher-order functions are you just talking about in the sense of having to deal with JS quirks or just in general you don't like HOF?
Just in general, and the dislike is stronger when working with CLJS. :)
Less clear stack traces, harder to inspect the resulting functions, often more code than a plain #(...)
.
Fair enough. As my programming/clojure skills improve I've been leaning more and more towards those HOFs like partial
and comp
. As you mentioned, part of that is because I am trying to wrap my head around transducers as well.
I'm also fairly certain the core team is inclined more towards lambdas as well. E.g. this comment is interesting: https://clojurians.slack.com/archives/C053AK3F9/p1634949659075500?thread_ts=1634948172.074200&cid=C053AK3F9
@dnolen I wonder - do you use some Slack bridge with some client other than the official Slack desktop client?
has anyone completed this Learn Clojurescript book: https://www.learn-clojurescript.com/
I can not figure out how I am supposed to run the chat project we build in Section 4. https://www.learn-clojurescript.com/section-4/lesson-26-capstone-4-group-chat/
That's seems really weird: • For some reason, the backend is completely separate from the frontend (assuming I understand the projects correctly) • The backend is in CLJS, not CLJ • The backend uses vanilla CLJS compiler and lein but the frontend uses figwheel-main and tools.deps (well, at least here https://www.learn-clojurescript.com/section-1/lesson-5-bootstrapping-a-clojurescript-project/ the book seems to be talking about building the latter) I've seen this book mentioned before, and it was either in the context of "yep, it exists" or "I don't understand X and it's not explained". I haven't read the book myself but just judging by the questions of others, it doesn't look that good.
Yeah, I have mixed reviews on it. I learned a bit just because it can be quite hard finding learning material for cljs (especially stuff that introduces some generic web development stuff for us less experienced folks) but things like this kind of drive me batty. It took forever working through that chapter.
No clue about the rest of the book, but the code for that particular chapter seems to be focusing on manually creating the required DOM elements at run time. Which doesn't make much sense either - I don't think that knowledge will be that useful. Sure, you'll learn something along the way, but it'd be better to learn something else entirely, something that actually gets used. If you want, I can recommend some particular steps that, once complete, should get you to the level of understanding that's enough to build complex web apps. I can't recommend any books though since I myself almost always learn from documentation and examples.
The very next chapter of the book is introducing react and then reagent so maybe it wanted to build up from lower level principles.
React and Reagent are absolutely much more useful. I really doubt manually creating DOM nodes can build up to that. Learning HTML+CSS would, but they don't really do that.
Anyway. All web apps have at least one component - frontend. Most also have the backend and a way to communicate. The backend part is vast on its own and there are plenty of good Clojure materials so I won't talk about that. Communication channels are also a large topic, but the main things that you need to know are: communication can optionally be bidirectional, communication can fail, communication can take a long time, and, depending on the communication channel, messages can arrive in a different order.
Now, to the frontend. The most common UI library in CLJS world is probably Reagent. It's built on top of React, and it, in turn, is built on top of HTML (well, in a way).
So, to be effective with Reagent you should have some understanding of React. Fortunately, React has great documentation, so I definitely recommend skimming through that and reading parts that seem the most salient.
A robust knowledge of HTML and CSS is also required because that's what ends up making the whole web page. The most important parts of HTML are basically a few standard tags and the way you can nest them. The most important parts of CSS nowadays are probably flexbox and grid. MDN website has some really good materials on both HTML and CSS, and I recommend ignoring W3School - they have too much incorrect information for my taste.
So, at this point you have a grasp of HTML and CSS along with understanding the concepts behind React. Your brain should be ripe for tackling Reagent. It also has great documentation, but it's a bit scattered unfortunately. I'd recommend going to their website (linked at their repo), then reading Intro followed by News (from the oldest to the newest). There's no that much to read - it just looks like it's a lot, but many links contain very short excerpts. The bulk of the Reagent documentation, and the bulk of the info you need to be effective with it, is in the doc
folder within its repo. Definitely at least skim through each document there. Way too often people simply don't know that something exists, and pretty much all usage scenarios are already documented in doc
.
All that by itself should give you enough building blocks to create anything you want. And if you ever start wanting to manage your app's state in a more centralized and reasonable manner, take a look at re-frame. Its documentation is great and definitely worth a read in full.
A few final notes:
• Don't stop experimenting with every single new concept you learn. Maybe skip in experimenting with React since that would require setting up way too much stuff that you won't need later - just hold onto those experiments till you can replicate them in Reagent
• I see people recommending this book rather often: https://pragprog.com/titles/dswdcloj3/web-development-with-clojure-third-edition/. I haven't read it myself, but it looks like it goes over pretty much all the stuff that I mentioned, plus much more. If books is a medium that you prefer for learning, I'd definitely give it a read.
• Just in case - never hesitate to ask questions, but always spend at least a few minutes first trying to figure things out on your own
Oh, one more thing. Different books and projects might prefer different tools, but I would highly recommend sticking to shadow-cljs + tools.deps (`deps.edn`). It enables a very flexible and manageable way to build and run stuff, quite unparalleled in my experience. Shadow-cljs also has excellent documentation with around 95% of all use cases covered.
Awesome stuff. Thanks so much. Fortunately, I seem to be on that exact path. I have that book. I also paid for Jacek Shae's reagent/re-frame/reitit courses back when I had some money. The reagent course was great back when I did it a while ago so I am going to review that too. I'm definitely on the shadow-cljs train. Part of my frustrations with that Learn CLJS book was it uses figwheel for everything but conjure
doesn't play too nicely with that so I was converting it all to shadow-cljs.
My biggest issue is getting out of tutorial hell. I've been self teaching myself all this stuff as a hobby but just recently I decided I want to give it a go professionally so am looking to create my own projects now. I have a full stack app I want to try and create. I'm also thinking of doing this 7GUIs challenge as I think that would help build up my frontend skills. https://eugenkiss.github.io/7guis/ The guy who started Roam (a full stack clojure app with some good buzz) was using this as a gauge for possible new hires but has since decided against that.
Just as an introspective side node: pretty sure I generally don't like courses and books on software development for one specific reason. New things often make me think "wait, what if [...]", I end up experimenting more than the course/book needs me to, end up reading usage documentation, API documentation, examples, source codes. And in the end, when I'm satisfied with my little experiment and get back to the course/book, I'm usually so far ahead on the learning curve that it's pointless to go on. But that's only relevant for specific technologies. A more generic materials, like that "Web Development with Clojure" book, are still good because they provide overviews and principles that are usually incredibly hard to figure out from API docs and experiments. Such insights often require years of experience, and reading a book definitely sounds like a time saver here. Regarding 7GUIs - yeah, definitely do that. It's a nice set of simple tasks where if you can't complete something then it means that you have some gap in a more or less specific area. Makes it easy to learn and self-correct. And after doing that, just start making that full stack app! :) You'll rewrite it dozens of times - that's alright, it's a part of the whole learning process. Much better than watching tutorials over and over again.
One other approach useful for learning. When you think you came up with an approach for some specific task, try to distill its essence, create a small code example that demonstrates the approach, and simply ask somewhere here or elsewhere what other people think of the approach. The insight of others in such cases is often invaluable.
@p-himik but that thread was just simply too long for something with a straightforward answer
Because the thread discussed multiple things. :) Apparently the imports work differently in nbb
and Node-based REPL. And, maybe, krell
. But in the end, the conclusion has been reached.