10 ms·
Learn ClojureScript: Discovering Sequence Operations
- Zelphyr 7y agoI’ve been going through this book lately and it is very well written. It’s one of the best introductions to Clojure and ClojureScript that I’ve found.
- vikeri 7y agoGreat to see people putting effort into making Clojure(Script) more accessible! As much as I like the language and the community, it historically wasn't a very beginner friendly place in my opinion. Not that people weren't friendly towards beginners but just a lack of resources targeted at beginners.
- bikeshaving 7y agoI stopped using clojurescript around 2015, primarily because I was tired of searching for/implementing clojure-idiomatic wrappers around the many javascript libraries out there. Put another way, I left clojure on good terms, and often missed its core functions, immutable data structures and lisp syntax when writing front-end applications. However, since then, javascript has changed a lot, specifically in terms of execution-suspending operators like async/await/yield/yield*. Meanwhile, the core clojurescript team has almost completely ignored these developments, preferring the immutable seq abstraction over iterators, and the core.async channel abstraction over promises/async iterators. For this reason and this reason alone, I’ve personally stopped considering clojurescript as a viable technology or recommending it to others. I have no idea how comtemporary clojurescript developers interoperate with javascript libraries and built-ins which are now overwhelmingly promise-based when async. I am also incredibly skeptical of the core.async channel abstraction as an alternative to promises/async iterators insofar as I think it is strictly inferior to both promises and async iterators because: 1. There’s no standard way to communicate error conditions. 2. There’s no logical separation between data producers and data consumers, and any code with access to a channel can take or put values. 3. There’s no way to communicate nil values insofar as core.async chose to use nil to represent end of iteration. I do not understand the decision by the core clojure team not to support promises or iterators, because one of clojure’s main selling points was pragmatic interopability with host language features. Nevertheless, I infer it must be an intentional decision not to support them, insofar as it’s so easy to support new language features in clojure with macros. Maybe it comes from a desire to adhere to “functional programming principles,” but I’ve found async/await, promises, and iterators/generators to be incredibly useful, so much so that I am unwilling to give it up for clojure’s immutability or nicer syntax.
- wellpast 7y agoAt first glance the cljs community doesn't seem short on libs that give await/async-like abstractions and from what I recall JS interop in CLJS was smooth enough to operate directly against Promise objects. In Rich Hickey's famous / often-referenced "Simple Made Easy" talk he lists what he considers simple vs complex toolkits. [1] There's a clear preference for declarative constructs vs imperative constructs. Async/await is attempting to take async behavior and make it "appear" synchronous. I suspect Hickey would slot this into the complexity category. At least I tend to agree. I think channels are both explicit about what is going on and also maximally decoupled/composable. It seems that your preference leans the other way. I just point this^ out b/c it is possibly or likely an explicit choice and not a miss by the Clojurescript team (Nolan?). I personally find the freedom given by Clojure/script ultimately simple and powerful. Curious for others' thoughts on this. [1] https://www.google.com/search?q=%22simplicity+toolkit%22+hickey&source=lnms&tbm=isch&sa=X&ved=0ahUKEwiBj9S1lKnlAhVJLKwKHXBSDgkQ_AUIEigB&biw=1467&bih=750 https://www.google.com/search?q=%22simplicity+toolkit%22+hic...
- ithkuil 7y agoI'm confused. Doesn't core.async do the same? The go macro applies a transformation on the body that is analogous to what happens with async/await. The difference is the async/await contract is built on top of promises which define a single future value or an error, while core.async uses a channel which can only yield non-nil values (no place for errors). Yes, you can do more with channels. But you can also use them to implement simple "blocking" calls that return one single value (This is used quite a lot in Go, where doing basic blocking IO on a file involves underlying channels between a facade layer and IO scheduler thread). Presenting an illusion of sequential code is precisely what core.async does. It's magic and hides complexity (which can leak back and bite you)
- wellpast 7y agoYou're not confused. I think you're right that both cljs/go and js/async blocks are giving a 'procedural way' to basically create an asynchronous processing/state machine. It would be interesting to see a fully-baked out analysis of async/await vs go and Promises vs channels. I do think Clojure still has the win on simplicity if for the main reason that core.async is just a library [2] and Javascript implements async/await via syntax with the actual implementation at a subterranean level. Clojure's version (core.async) can be macroexpanded/unwound -- i.e., the 'magic' you speak of is not magic at all and can be examined and implemented directly w/in ClojureScript itself. From the channels vs Promise perspective I think there is more to argue. Channels are quite a simple concept when weighed against the Promise spec [3]; of course this is arguable and arguments welcome. Also worht considering David Nolen's takes, one of them here: [4] [1] https://clojure.github.io/core.async/ https://clojure.github.io/core.async/ [2] https://clojure.org/news/2013/06/28/clojure-clore-async-channels https://clojure.org/news/2013/06/28/clojure-clore-async-chan... [3] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... [4] https://swannodette.github.io/2013/08/23/make-no-promises https://swannodette.github.io/2013/08/23/make-no-promises Edits: typos/cosmetic.
- js4ever 7y agoClosure seems to focus on purity instead of productivity. When I read this article I imagine my team spending days to implement basic features they could implement in few minutes with vanilla JS. Business don't care about code purity. Only security, performance and correctness really matter.
- capableweb 7y agoI can understand where you coming from, Clojure developers take a lot of time to think and discuss what seems to be irrelevant (to the business) details of software engineering. I can ensure that it's not like that at all. Clojure is a very productive language (see: focus on repl, clojure.spec and similar efforts) and also pragmatic. If you and others have the feeling that it seems like a unproductive language, I invite you to take a closer look. Once I sat down and actually tried hard to learn it, it didn't take very long to get productive in it, compared to other languages I've learnt.
- iLemming 7y ago> Clojure developers take a lot of time to think and discuss what seems to be irrelevant (to the business) details of software engineering. I beg to differ. I don't know how, maybe due to my experience and knowledge, but working with Clojure developers, discussions usually levitate towards the business problems and not the language ecosystem and tooling. Language just gets out of the way, it does not impede, does not slow you down, the distraction is minimal. In other languages there are always talks about the syntax, about styling, about dependency conflict resolutions, subtle bugs that may or may not happen. In OOP languages - class hierarchies and patterns, interfaces, etc. There is always at least one smart-ass "rebel" in the team who writes code, adding some "nifty" tricks and esoteric, gimmicky features of the language no one else in the team knows about. Of course, like any other language Clojure has "idioms" and like any other language it is possible to write "cryptic" code, but usually newbies learn those idioms quickly enough. Just like with irregular verbs in English - although they seem to be strange at first, you learn to use them because they are used very often.
- 7y ago
- jwr 7y agoHaving read most comments under this post, my conclusion is that the Blub Paradox is very real. I am surprised that otherwise sophisticated HN readers fall prey to it. I see a lot of comments which are outright dismissive, from people clinging to what they know, and in most cases not knowing much about what they are criticizing. Over the years I've learned that if there is something very different about a language or a solution, or if there is something I do not understand, it is a strong indicator that it's something worth learning about. Sure, it might be worse than what I'm using, or might not be applicable to my use case, but usually there is something there worth investigating, and sometimes you discover a better way to program.
- lbj 7y agoAs someone who has been doing Clojure/Cljs for a long time, I really appreciate it whenever someone goes the extra mile in explaining the basics - All the things clojurians take for granted in their every day work. Kudos to the author!