6 ms·
My biggest complaint remains that without a meaningful concurrency story in js, the benefits of clojure dont make much sense to me. Its just another hard to de
by shadowmint 10y ago
My biggest complaint remains that without a meaningful concurrency story in js, the benefits of clojure dont make much sense to me.
Its just another hard to debug compiles to js language.
I get you can share some code between server and client... but we've used it in production and now we're getting rid of it; there just wasn't a compelling reason to keep it over es6.
- glenjamin 10y agoJavaScript has no meaningful parallelism story, but every single asynchronous action you take uses some sort of concurrency primitive. Even hitting submit twice on an standard ajax powered form is likely to cause mild concurrency-related bugs on many popular websites.
- glenjamin 10y agoJavaScript has no meaningful parallelism story, but every single asynchronous action you take uses some sort of concurrency primitive. Even hitting submit twice on an standard ajax powered form is likely to cause mild concurrency-related bugs on many popular websites.
- smnplk 10y agoI find your decision surprising. >> there just wasn't a compelling reason to keep it over es6 << How about these reasons: - much simpler language - core.async channels/ no callback hell, easier to read async code - persistent data structures - great sequence abstraction - live code reloading - vibrant community - improved tooling - macros - transit
- drawnwren 10y ago>> - much simpler language Given that it all compiles down to JS before execution, I'm not sure I agree. With Java, you're going to bytecode operations which (imo) allows for a simpler language than compiled to. >> - core.async channels/ no callback hell, easier to read async code I agree, callback hell sucks. I'm not sure that core.async is a huge win over promises, but this is an area that JS is quite horrible. >> - persistent data structures >> - great sequence abstraction I'm not sure I see the benefits of clj's sequence abstraction over js. You get destructuring and sequence comprehension in es6, although clj's recur/callstack fix is quite nice. >> - live code reloading - vibrant community - improved tooling - I'm pretty sure all of these are better in JS than CLJs. >> macros - transit Macros are the old LISP fallback, but seem very counter to any argument of 'simplicity,' I very rarely find need for macros in the front and Clojure's design philosophy generally favors not using them (Data > Functions > Macros) I do like CLJ and CLJS is interesting, but the only reason I really reach for CLJS is if I am feeling like writing something in om.next.
- fnordsensei 10y ago> Given that it all compiles down to JS before execution, I'm not sure I agree. Most likely, they meant "simple" more in the syntactical sense than in the sense of language abstraction level. > Macros are the old LISP fallback, but seem very counter to any argument of 'simplicity' Macros is just transformation over a data structure, albeit a data structure that is interpreted as code later on. It shouldn't add more complexity than other forms of data transformation. > I very rarely find need for macros in the front… Neither do I, but I'm glad they exist. Core.async is built with macros, for example. They are part of what makes it possible to have core.async as a library rather than having to build it into the language.
- drawnwren 10y ago>> Most likely, they meant "simple" more in the syntactical sense than in the sense of language abstraction level. Outside of the Clojure world this would be a reasonable interpretation. However, if you watch 'Simple made easy' by Rich Hickey - that was the definition of simple I was going with (as opposed to easy.) >> Macros is just transformation over a data structure, albeit a data structure that is interpreted as code later on. It shouldn't add more complexity than other forms of data transformation. Because they specifically inject before the eval section they _do_ add a lot of complexity. Writing complex macros is a lot of guesswork. >> Neither do I, but I'm glad they exist. Core.async is built with macros, for example. They are part of what makes it possible to have core.async as a library rather than having to build it into the language. I'm not sure what the benefit of this vs 'language features' is at this point.
- kazinator 10y agoMacros de-risk themselves by going away before compile time. So even if they are complex, they are not complex in a way that causes us to lose sleep at night wondering "does that have a hidden bug that will blow up in the field". Even if a macro is buggy, if the particular instances (i.e. macro calls) don't step on the bug, then we are okay. The expansion is done, and it is good. Macros are deterministic and susceptible to regression testing with simple "X translates to Y" assertions. We don't have to be overly concerned with the time and space performance of macros, either. The code in a macro expander can be structured for clarity and remain that way. (Even in situations in which running Lisp apps are patched, the macro expansion doesn't have to be done in the application image. The translation unit can be compiled using a separate development image, and loaded as compiled files in the running app.)
- shadowmint 10y agoTo be fair, the only thing if your list which is actually tangible is core async, the rest is just personal opinion (live reloading and vibrant community I question somewhat, just because javascript has both too). ...but really, it boils down to the fact that the people who were writing clojurescript in house wrote terrible spaghetti code that didn't work. Without a tangible justification for re-writing (again) in clojurescript, the decision was made to rewrite it in es6 and throw all of the clojurescript away. I think the lesson here is: Having an excellent language (Clojure) can't save you from writing bad code. For some reason writing clojurescript resulted in code that was a far lower quality than the clojure code from the same developers. /shrug I can't explain why that is, but for us, it boiled down to: If you can't play nicely, you can't have nice toys. Quality of the end product is more important than the tools used to build it.
- Touche 10y agoJavaScript has concurrency (at least in the browser), Web Workers. Messaging isn't always a "nice" way to work, but a layer of abstraction (like a language) can make that better.
- jgalt212 10y ago> Its just another hard to debug compiles to js language. Using Figwheel, this is just not true. I do see ES6 making life hard for the compile to JS languages, though.
- bpicolo 10y agoI've written a decent amount of Clojurescript, and painless debugging is definitely what was missing for me. The callstacks are pretty useless internals, figwheel being outside the browser and away from the visual breakpoints and such are kinda hard to deal with compared to JS. Not that JS doesn't have debugging pains either, but really the debugging story is the worst part of clojurescript.
- tosh 10y agoThis should get better soon with clojure.spec
- bpicolo 10y agoHow does clojure.spec help debugging in any way?
- fnordsensei 10y agoOne of the things it does is to tell you where something went wrong, and why. Assuming you've provided a spec for it to use, that is.
- jgalt212 10y agoyes, but that's only for objects that you have spec(ified). It really would be a lot of work to do for every variable, and you'd quickly hit the point of diminishing returns. Another thing to consider is how many of your bugs are because of an ill specified object, or because i held null instead of integer.
- pandeiro 10y ago> there just wasn't a compelling reason to keep it over es6 - hiccup syntax / sexps are trees analogous to the HTML you're constantly generating, and first-class supported data structures supported by the language which need no pre-compilation/transformation step, unlike JSX - syntax is a good 20-30% less verbose than JS (yes, even ES6), especially when the core lib is taken into account (things like partition, zipmap, threading macros) - one extremely battle-tested dependency resolution story, not named NPM - it just works - incredible development tooling innovation, best of class for frontend web development - the sequence abstraction and dozens of functions that operate on it, rather than Object.assign, Array.map, etc - best-of-breed dead code elimination via Google Closure Compiler, meaning much of third party libraries and development-specific code ends up weighing less / nothing in production builds - sets and set operations built in, along with tree walking, diffing and string utility libraries, included with the distribution - no more defensive copying, thanks to immutability everywhere
- nickbauman 10y ago> one extremely battle-tested dependency resolution story, not named NPM - it just works This alone is worth all of it.
- edem 10y agoYep. Leiningen is even better than mvn/gradle combined.
- glenjamin 10y agoLeiningen uses the exact same dependency resolution model as maven and gradle. It has many advantages over those tools imo - but its dependency resolution model isn't one of them.
- nickbauman 10y agoWhat kind of dependency resolution model would you prefer?