Hacker News new | past | comments | ask | show | jobs | submit login
Why ClojureScript Matters (juxt.pro)
198 points by jonpither on June 29, 2015 | hide | past | favorite | 116 comments



I think that the main argument presented in this blog -- "avoiding splitting" is wrong :Splitting the development into frontend and backend is essential for developing maintainable code for large projects. Having a well defined communication api between backed and frontend defines responsibility for front end and backend developers and also enable better (j)unit test cases. The communication overhead and associated documentation is beneficial in the long run as the code that is produced will be better understood by all , not just the lone developer; it also makes code reviews easier and allows new developers to take over existing code base when necessary. It is immature to think developers will only feel pride in their when they own the entire codebase, the ui-to-db stack; The idea that "Lovingly crafted aesthetics in a codebase is key" is silly; code needs to be testable, well documented and highly optimized and re-usable.The "jostling of positions" are design discussions and they are important part of the software development cycle.

I like Clojure and I am interested in learning ClojureScript but this blog post makes a poor case for it.


That's a nice myth, however in practice what happens is exactly the opposite, mostly because people lose sight of the whole picture and end up super specialized on small pieces of the puzzle. This is what happens in corporations, where the whole reason for why projects succeed is because of the invested resources, work still being done on the model of the Egyptian pyramids, with thousands pushing large bricks. There's a reason for why micro-services that don't start as a monolith are failing - people have this impression that micro-services are imposing clearer boundaries, which is of course wrong.


The danger of having people who aren't specialized is just as great as the danger of having people too specialized.

Backend and frontend concerns are completely different, and it's fiction that you can simply wave those concerns aside and write the same sort of software anywhere in your stack.


I disagree and I think that treating the frontend and backend as different concerns is one cause for the big balls of mud we end up with. For example, many treat the backend as if it doesn't require design or taste for good user experience and many treat the frontend as if it doesn't require solid engineering. They are wrong of course.


Splitting teams along the API boundary is a sure way to get crappy API's. To get good API's you need to dogfood the API. In other words the team that writes the server side should be writing at least one of the clients consuming the API.


I'll go a step farther... the consuming API client should be in a different language/idiom than the server-side implementation (assuming multiple languages are going to be used in your environment).

Too often I try to access Java or PHP web services from .Net, where the tooling is very strict, and it just falls apart. Or I'll have to use something via JS that is just excessively painful to use in practice for no good reason.

I've also seen time and again layers of indirection or other design patterns used without any consideration of why they are being used in that instance. You don't have to hide your data tier behind factories of repositories. You don't have to make everything an interface. If you aren't going to test anyway, make the code as simple as possible. I tend to favor only adding complexity if it makes those complicated pieces easier to use in practice, and even then not all the time.

Sorry for the rant, I just see time and again certain levels of complexity without flexibility or consideration for why.


> Too often I try to access Java or PHP web services from .Net, where the tooling is very strict, and it just falls apart. Or I'll have to use something via JS that is just excessively painful to use in practice for no good reason.

On the other hand trying to use anything from .NET land that implements WS-Security from PHP or Java is also exceedingly painful. I recently had to integrate very similar APIs from 5 different companies into an internal application...

One used an HTTP(s) REST API written in PHP, it used mod_auth and I was done in 30 minutes.

One used SOAP with some custom extensions, I hacked around a bit with the PHP SOAP classes and was done in a few hours.

One used WS-Security, and after a few days of hacking around I ended up using Netbeans' tooling to generate a Java client that could consume the service and forward the results to PHP.

Another used a (more recent) version of WS-Security and the same trick wouldn't work, so I contacted their support who admirably tried to create a java client to consume the service, gave up, and created a regular SOAP bridge for us to use.

One company is still trying to get our AD credentials set up with their vendor software that uses Biztalk somehow (they've been scarce on the details) after two months of waiting.

RESTful services in PHP and Java may not have a pretty GUI configuration tool, but they are much simpler to get working than SOAP and any of the MS extensions in my experience.


It's worth noting that you can mount very simple SOAP services in .Net (doesn't mean that people do)... WCF for example gives a lot of ways to mount your services together, or separately.

That said, I've never really been a fan of SOAP in general, and WS-(death)* is painful in any system. Funny enough, I've found node.js to be the easiest middle-man to coerce into using different services as a gateway, and it's my go-to when a wsdl doesn't import cleanly into a .Net project, and just define my own JSON/REST interface in front of the foreign services for the parts I need.

AD integration is particularly painful, and pretty much only works in IIS, in that case, I'd lean towards writing a shim in ASP.Net MVC exposing JSON endpoints, in a similar fashion.


(apologies for replying to my own comment, but I want to highlight some reasons by division of labour between backend and frontend development work is important).

Typically, backend developers need to have specialized knowledge of the enterprise security system which needs to be invokoked for authorization requests. Also the backend developers need to worry about availability/clustering issues. They also have to be familiar with caching subsystems in place , observe or predict the api requests patternt and implement caching strategies. They have to deal with a 'different scale' of concurrency issues than normal ui devs. The there is the issue of api versioning: there will be clients/user who will not upgrade and the backend development team has to figure how to support multiple versions of the same API. Then there is the issue of deployment and packaging: not every development shop lets developer push deployment into directly into production.Then there is the issue of database queries : you will have to optimize those heavily in consultation with your database admin. If you are using JVM, you have to optimize that for your application. The frontend development work has its own set of equally vexing challenges.

There is no doubt that any competent developer can handle all these tasks but it won't be the kumbaya singing utopian happy habitable code paradise that this blogger is seeking. Division of labor between backend and frontend is a life saver for developers. I would actually want to go home and not spend my life in this "habitable" place.


I agree that there things work differently on the server and on the client but the lines are getting blurred. For example, you might not need api versioning if you only write a SPA application, there is usually some caching on the client also and it seems to increase, the concurrency problems are starting to show up in the clients (promises and callback hell) and sometimes you want to duplicate a lot of the security things to the client to give faster feedback and a more dynamic gui. Database queries are probably mostly done on the backend but there might be queries in some rest format in the client that are sent to the server and there might be IndexedDb queries instead.


Sure, any large code base needs to be modular, but why impose an arbitrary split?

We've got a large Node.js codebase. Some of the code runs only on the server, some runs only on the client, but the majority runs on both. Our code is split into modules for functional reasons.


The split between backend and frontend is not arbitrary; it is based on client-server paradigm and it has worked well.


I'm not sure why you're getting downvoted, because you're right. To be more specific, server code has very different responsibilities than client code, not to mention very different runtime characteristics (e.g. servers are both trusted and under total central control, unlike clients).

To say that the client/server split is "arbitrary" is rather silly.

(That's not to say I'm not a fan of an end-to-end language. Meteor shows what you can do with this. Maybe ClojureScript can do this, but with a better language.)


He is getting downvoted, and rightly so, because the person is replying to has clearly set up his system is such a way that some code runs on both the server and the client.

Which is very reasonable, btw, as it allows you to have a static site that renders for those whoes browsers doesn't run javascript and a more dynamic page for those whoes browser does run Javascript. You are guaranteed that everything renders the same way only if you excecute the same code (this can't be replaced by e.g a sensible template system because rendering might also be affected by how you, e.g, sort comments).


We're doing that too, but that's the boring part. That's just running client-side code on the server. It's still client-side code. You can do that in Rails too. See my other comment for more details.


If you are running client side code on the server you use a very different definition of client side code than most other people, which is bound to be confusing.


We have lots of code that runs on both the server and the client. It has the same responsibility whether it's run on the server or the client.


Can you provide some examples?


To oversimplify, if the user clicks on a button on our website, the app checks to see if the operation can be done client-side. If it can be done client side, it's done client side instantaneously. If it's too big to do client-side or requires access to resources that aren't available on the client, the app submits a job to the server, and shows the client a progress bar.


They're talking about the split of programmers, not of concerns. The client-server model is definitely here to stay but having separate groups of people handling each side is a sure way to greatly lower the quality of the product.


You mean that one needs competent developers? That is nothing new. At least a few of the developers should now both languages and sides.


> but the majority runs on both

What does this mean exactly? What kind of code needs to run on both?


I tend to agree with you, but there are things that can/should run on both - validation of input for one. But I'd like to hear other things - I hear "use the same code on the server and client" all the time, but I haven't found a lot of use for that personally.


Turning a reactive web application into a regular "web site" -- ie. allowing you to use the bulk of the application without Javascript enabled. Great for SEO, too, at least until Google gets Javascript execution further along (which it's certainly doing, and getting better every day).


Another common example is something like a Markdown/BBCode parser.


The Meteor framework [1] uses this to good effect to support latency compensation.

You can optionally choose to include Meteor methods (ajax-style remote endpoints) on the client. Then when the method is called, the client-side version is run in addition to the real, server-side one being kicked off. If the server-side returns an error, such as due to insufficient permissions, the changes made client-side are rolled back. Combined with Meteor's client-side mongo implementation and reactive UI updates, it gives impressive "perceived performance" benefits.

1. https://www.meteor.com/


Aside from things like general libraries (e.g. serializing/deserializing data to/from the client), anything you want to happen client-side that you don't trust the client for, you will need to re-run on server side.

A simple one is validation of forms, but also doing rapid UI updates without having to do network round-trips.


template rendering

validation

routing

modular business logic e.g. - calculate total interest paid over the life of the loan provided the client pays x per month etc etc


The one thing that I don't understand about his argument is why having dedicated QA is bad? Having QA doesn't mean you shouldn't test your own code, but you have blind spots when it comes to testing your own code. It is easy to make assumptions about how your code should work.


The post has a good core, but is wrapped in opinions like this which detract. I agree with you entirely: I produce my best code when I test everything, and then someone else tests and discovers the parts I excluded from 'everything'.


I think Clojure owes much of its success to the acceptance of using multiple languages in the same project.

Maybe breaking off a small piece of functionality in a Java project to try implementing in Clojure.

Maybe implementing a service with a REST API in Clojure accessed from clients written in other languages.

So I find it a little ironic, and maybe short sighted, to hear "write everything in one language" used as an argument for using Clojurescript.


I agree, if the one language idea really starts to be followed everywhere it is probably javascript that will win. There is almost nothing in this article explaining why clojurescript is or could be a better choice.


Having a well defined and documented API is not an artifact of splitting development roles between front and back end. There are many, many projects out there with split roles that have terribly defined and ill-documented server interfaces.

It's an artifact of having competent developers, be they full stack or not.


Agreed. The client-server abstraction is one of the very best in the history of computing. I don't know why so many people are trying to do away with it.


The article doesn't mention doing away with client-server architectures but rather the separation of frontend and backend programmers which is indeed very harmful.


I think trying to write your apps in this way hides the underlying client-server architecture.


I've written a clj/cljs app with source sharing, and there are many downsides. Tooling, lack of progressive enhancement, debugging, download sizes.

I feel the benefits are worth it for my use case, but it's not all roses.

But hiding the client server architecture is just a bizarre criticism to me, because it's not at all what writing one of these projects is like, and I'm not sure how you're even getting that impression.

The degree to which you share code depends on how much functionality you are replicating, and is code that you would literally be cut paste porting if you were using another toolset. Or just avoiding writing altogether, like speculative updates.

Just because you can theoretically attempt an antipattern doesn't make a tool bad; you can write shit in any language. And many do.


It's not an abstraction, it's an accidental byproduct of physical hardware placement.


Client server is about having more than one consumer that needs to share and mutate the same data. In other words, collaboration. In general the pattern doesn't care where the hardware is located.

Remote hardware just accentuates issues that are only obvious due to high latency. A local system for example could get away with a less sophisticated locking mechanism... until it doesn't.


You're right, but current agile dogma frowns on that. I think a lot of us like being a "full stack" developer too. It's part of our ego that we like going from our procs to the css


I disagree with some of the statements about developer pride. I was reading https://speakerdeck.com/garann/code-is-a-job this morning and it's a position I have a lot of sympathy with.

Not having the backend developer/fronted developer split is good; while each will have its own specialities, they shouldn't be siloed into separate teams.


Thanks for sharing. Good read.


As a data point, I've just written a significant ClojureScript application, using React (Rum for bindings, Datascript for client-side db). It's amazing how quickly one can create complex apps with impressive performance out of the box.

If you haven't used ClojureScript, it is definitely worth looking at.


Can I somewhere find a good Rum/Datascript ClojureScript application that is easy to understand? Maybe something with a blog post that goes into how to set up such a project.

With ClojureScript I always have probelems to get running, and how to devlop effectivly. All the information are old and outdated.

I love the idea of DataScipt/React but I have not really done to much until now.

Edit: I know of the creaters blog, but I would like more.


Nikita's blog posts are pretty good. I found this one to be informative: http://tonsky.me/blog/datascript-chat/


How did you select your components? I've never heard of Rum or Datascript, for example.


Nikita Prokopov has presented a pretty cohesive vision for front-end programming in the cljs community. Even if you don't agree with all of his opinions, he's one of the only people assembling a big picture about how to write apps in this way. It's worth reading his blog:

http://tonsky.me/

An emphasis on low-level tooling and not enough discussion around high-level architecture/examples has hurt the react+cljs combo adoption from my point of view. It's the nature of Lisp to come up with your own abstractions around application architecture, but the community would be wise to talk more about solving common web patterns and how to cleanly break away from those patterns when necessary.


Thanks for pointing me to his blog. He's a great read. Got anything else by him I should read/watch/listen?


It's true that it isn't that easy to discover new libraries, especially as there seem to be lots of them popping up. You generally hear about these things from the community (which is great, btw!), or public talks. Nikita Prokopov is a brand by now, so I tend to watch his work closely.


One of the concepts I really like about cljs frameworks like Om and Reagent is the concept of a single hierarchical data structure that components read from/write to. This concepts makes thinking about my app and its structure so much easier.


I'm curious if this is a project you could share?


PartsBox, https://partsbox.io/ — but the app itself isn't public yet, it's in a private beta for now.


If Om hurts your brain, I can't recommend Reagent enough: http://reagent-project.github.io/


Reagent presents a very simple api at the expense of a lot of complex/magical bookkeeping to link components and their update cycles to a framework-specific application atom. If you're really looking to demystify how clojurescript can wrap React, I can't recommend reading through the source code of Quiescent enough:

https://github.com/levand/quiescent/blob/release/src/quiesce...

That said, I've really enjoyed Reagent for prototyping, and the magic is the good kind of magic. It's just that Quiescent feels so much like a clojure library, trading ease for simplicity — and is often a better brick to build your own abstractions on top of.


Can you explain why Om hurts your brain? I've heard other people say similar things, but I've never quite understood why. Is it cursors? Local component state?


OM components are complex. There are global transaction/message channels, component local state, an OO backpane, lifecycle functions, functional zippers, hierarchy organised data, etc. I can't understand how anyone could claim it to be simple.

Look at this example code, apparently held in such high regard that it is referenced off the front page of OM: https://github.com/swannodette/om-sync To me that is a ghastly, inexcusably complected hairball.

Don't get me wrong. I really like clojurescript. I program in it daily, on purpose. It is just that I'm shocked at the level of devotion and adulation for OM when there are really lovely alternatives like Reagent and Rum.


Some inaccuracies here about Om. There are no message channels. There are no functional zippers. Component local state and lifecycle are critical React integration points. Hierarchy organized data is not required - people have succeeded at integrating DataScript. om-sync isn't even an official thing, just got tired of people asking me about a basic example :)

If you don't like Om, that's really OK. The real goal of Om was always to inspire people to consider and research alternatives to traditional client-side MVC. 16 months in I would say with the large number of excellent alternatives, Om very much succeeded.

I hope Om Next accomplishes the same broad goal and convinces people to seriously consider the big ideas behind Relay/GraphQL, JSONGraph/Falcor, and Datomic.


No zippers? Why then does the official OM docs say "Cursors are conceptually related to functional lenses and zippers". Remember this thread relates to how simple or easy OM is to grok.

And no message channels? Why then does the intermediate tutorial plunge straight into the use of core.async?

I have no problem with OM being considered a grand experiment. I wouldn't use it but it has been an interesting idea generator. Please remember context here - I was responding to someone who claims astonishment that OM could be considered difficult to understand.

But, in terms of grand experiments, let's remember that Reagent came out at exactly the same time as OM. And Hoplon lead the way on Reative (FRP) long before either. So, having lived through it, I'd feel very uncomfortable with any overreaching claims about OM succeeding in inspiring all the others into the alternative MVC holy land. The others were there already.


I also feel that Om is very complex. I'm sure I've spent over 20 hours trying to wrap my head around it but didn't manage to do anything.

From the people that know it well, they all love it. But I don't seem to have the required knowledge to understand it. I feel somehow dumb by that. The docs aren't good also.

After that, I've tried reagent for 30 minutes and ended up with a lot of progress and I'm currently writing my first cljs small app. Everything seems to work and it's like clojure.

You have an atom and just have to write views in a hiccup style, everything magically works.

Maybe I will try Om later and get it, but it's not simple. I've been able to wrap my head around a lot of concepts with easy in my life, but Om felt too much.


"From the people that know it well, they all love it. But I don't seem to have the required knowledge to understand it. I feel somehow dumb by that."

When I get this feeling, it's often because I haven't yet experienced the problems the new thing is trying to solve. Is it possible Om is an attempt to solve problems you haven't encountered?

I have no personal experience with Clojurescript (love Clojure, though), so this is just a generic comment.


I'm learning clojurescript in addition to (eventually) learning Om. I feel like Om provides you a lower level of abstraction than Reagent which is good for building some complicated web apps. However, as a CLJS beginner, Reagent and the re-frame framework have been easy to dive into.


Pairing with someone who's built a few Om apps should get you up to speed in no more than 45 minutes. I've done it a few times now, and it just takes a few examples, building some components, and composing them together.


I don't know anyone with interest in Om/clojure though :(


I think it's mostly a matter of personal preference. There are multiple React interfaces in ClojureScript: Om, Reagent, Rum, Quiescent being the most popular. Pick whichever you like.

I looked at Om, found it too verbose, and switched to Reagent. I then found it too limiting, so I ended up using Rum, which I think is the most flexible and the most minimalistic. I think it's great that we have the choice and that we can cross-polinate ideas between various libraries.


I use it every day, but there's always some aspect of its behaviour that it turns out I didn't understand the first time round. Perhaps that's because I jumped into the project with only a very rudimentary understanding of Om, just enough to complete a certain ticket. I've since then spent a lot of time going through the docs, but it just conceptually doesn't sit well with my brain. Sorry I can't give a more useful answer. Reagent on the other hand, which I haven't used in production, just "feels" better every time I play with it.

The thing that helped my understanding most was a recent project where I got to work with React directly. Also, reading the source.

So yes, it's mostly because I'm a little lazy, but Reagent doesn't seem to punish me for that same laziness. 😆

EDIT: More details.


While not a specific answer, "feels" is a valid response IMO. Like mentioned elsewhere, using reify seems to throw people off, which falls in to the "feels" category I think.


I think part of the reason some people feel this way about Om is that it was built as an experiment - specifically an experiment about handling immutable state in React.

I find that Om has very strong opinions about doing state the clojure way, but is a very thin wrapper around the rest of React's API - which leads to a feeling of inconsistency.

Some of the stuff David's suggested will be part of "Om next" I think will address this.


The inconsistency part makes sense, I guess I just never thought it was a big deal. If you're going to use WillMount, it's either going to be with reify (Om) or meta (Reagent). Doesn't seem like an important distinction to me, but obviously it is to some people. And that's totally legitimate.


It was mostly the whole reify dance, which I never had to do in any other clojure/clojurescript project.


I recommend using https://github.com/Prismatic/om-tools, if only for the defcomponent macro: https://github.com/Prismatic/om-tools#defcomponent

This abstracts out all the reify stuff and makes for far cleaner component definitions.


reify is usually a low-level construct in Clojure. A lot of libraries use it under the hood, I wouldn't be surprised if you use a few of them :)


Probably, but it still left me feeling a little alienated.

Not to take anything from Om tho, people using it seem to enjoy it a lot! I guess I'm just less smart ;-)


I wouldn't say less smart, it took me some time to get used to reify before feeling comfortable using it too. Think anonymous classes in Java for example, its almost the same thing.


Have you looked the re-frame framework? It's a FRP framework that utilizes Reagent for its views.


Taking the 'splitting' argument head on, I don't believe that having a planned split between 'front end' and 'back end' developers is a good idea at all.

I don't like that he seems to have to concoct that argument to sell ClojureScript. The argument seems artificial.

There's lots of reasons to decouple the front-end development from backend development. In fact, once you start using a client framework and use the backend as a service layer you can really decouple your layers. Doing web stuff, I primarily work in ASP.NET MVC and I'm trying to get rid of razor completely.

In fact, If I had my way, I'd have css/photoshop jockeyes (with a little angular/whatever knowledge) in charge of the client, a javascript/Typescript guy doing the client MVC, and a data guy doing Web API.

Agile tends to frown on these distinctions. I don't buy it , just like I don't buy a lot of the Agile dogma. Oh well.


I notice the author employing a bit of jiu-jitsu I see sometimes -- basically, that you shouldn't worry about designers not understanding ClojureScript (or whatever), because that is insulting to the designers.

But how about designers have 18,000 other things to deal with and maybe they aren't interested in learning (in their estimation) the latest wacky-ass way web developers invented to generate HTML. The point isn't that they couldn't understand it if they tried, the point is that they would have to try, perhaps to the exclusion of something they would consider more useful.


I agree with this. The author should've mentioned enlive (you got a similar library that supports om) which allows html to be html, which should make designers happy.


So I tried Clojurescript and I liked it as a language. In terms of fit for a compile-to-Javascript language, it is probably the best implementation out there, partially due to Javascript's dynamic lispy origin. But it has a a major problem: It's not Clojure. It might be a Clojure-like language, but its not Clojure. So you still end up "splitting", but when you split you have to squint harder at the details. As far as fidelity to the native language, I've found Scala.js to be much better.

I can't wait for WebAssembly though... it will be a game changer for people that prefer strong static typing for managing logical complexity.


I haven't used Scala.js, but I find Clojure and ClojureScript to be so damn close to identical I'm surprised at this comment. When I'm doing ClojureScript, everything I use from syntax, sequences, persistent data structures, core.async, protocols and records (the list seems endless) is the same as Clojure. The only thing that trips me up is regular expressions. In fact, I find there's a great deal more difference in the Scala written by any given two Scala developers than between Clojure and ClojureScript.


I've come to appreciate some of the new ES6 features (anonymous functions, lets) much more after using their equivalents in ClojureScript.

Also, The interactive REPL based workflow that a lot of the LISP languages utilize is extremely appealing. I've been thinking a lot about how to bring this back into the JS world. I have yet to find any good literature on it, but I will be exploring this area more.

For those curious, here are some blogs that convinced me to finally give Clojure a spin:

- http://rigsomelight.com/2014/05/01/interactive-programming-f... (seems like this is the stereotypical "you should try ClojureScript because... " post)

- http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-r... (a bit code-heavy, but an admirable workflow)

- http://swannodette.github.io/2013/11/07/clojurescript-101/ (dealing with asynchronous code)

I'm curious HN, anyone out there making strides in interactive JS development, akin to the 2nd blog post I referenced above?


Honestly this is the part I hate most about Clojure. The tooling is always so convoluted to setup and by the time you start your next project something has changed again, requiring more changes which might break your tool chain. ClojureScript is especially guilty of this right now with all the recent repl changes.

I appreciate the The CS team trying to work with 3rd party repl developers right now, but it doesn't seem to be helping much. It's pushed me back to simple gulp based es6 dev using ramda, rxjs, immutablejs, etc - basically the parts of clojurescript I like. The only thing I sort of miss from Clojure are macros and homoiconicity - it sure is nice to look so uniform, but the tooling just drives me away.


I can agree with that with clojurescript, but I disagree that clojure itself has this problem.

Clojurescript -should- be calming down soon. It is in a stage of changing constantly ATM but that should calm down once some of the underlying tech is stabilized (like clojurescript bootstrapped from clojurescript).


I get the same impressions. Even working with ClojureScript professionally for ~3 years, contributing to the compiler (a tiny, tiny bit), and diving deep into a lot of the libraries... the tooling story is way too chaotic for me.

But I'm somewhat OK with it, as the changes generally seem to be positive, and I have hope that the stability will coalesce around a good, rather than rotten-but-papered-over, core.


I feel the same way. The ClojureScript compiler routinely makes the conceptually sound choices even in the face of breakage. This leads to unstable tooling but the quality of the underlying code allows for bigger and better conceptual improvements.


Have you looked into Mozilla's SweetJS? I haven't had enough Clojure experience to get into something where macros would prove useful, so I'm wondering if utilizing macros in Javascript (which I'm much more comfortable in) would be worthwhile.


> I've been thinking a lot about how to bring this back into the JS world. I have yet to find any good literature on it, but I will be exploring this area more.

The JS equivalent of figwheel is React Hot Loader[1]. There's a port of core.async[2] but I've also seen people using Babelized ES7 async/await for avoiding callbacks. The reloaded workflow is just a pattern around building objects with a topological sort for order initialization. I expect you could build a JS version in ~200 lines of code.

[1] https://github.com/gaearon/react-hot-loader [2] https://github.com/ubolonton/js-csp

I'm unaware of editor integration between an editor and browser runtime a la slime/nrepl. I think LightTable had a basic implementation but it's been a while and I could be remembering it incorrectly.


Much more relevant than WASM in 2015 is that modern Javascript development is also moving towards compilation. There's little fundamental difference between compiling ES7 via babel.js vs compiling clojurescript.


I had a similar thought, though for me that's a reason to keep using Babel and ES.next rather than ClojureScript. I find lispy syntax difficult to read.


One thing Clojure/ClojureScript desperately needs is an answer for progressive-enhancement.


No it doesn't. You can literally do the same thing you did with PHP in 2007 if you want to (have a controller that outputs xml to be transformed into jquery commands if an ajax call or renders html if not ajax). You could also do something less silly like share your templates (maybe via hiccup and its many cljs implementations or via enlive/enforce/kioo (or via Soy, or anything else really)). If you want to get really fancy, you can actually just render your js server side via nashhorn and then rebind whatever modern rendering library you choose (React, Ember, etc) onto the rendered html at runtime. This is all ignoring the fact that nothing prevents you from serving html from server-side templates and keeping your cljs codebase completely separately ala most web apps (then progressively enhancing with whatever you normally would).


It really does. Isomorphic is the new standard. Doing it in a very manual way is not good enough. Every new JS framework is expected to do this out of the box and the older frameworks are scurrying to gain support.


React literally does this out of the box. Om does it (based on react). Reagent does it (based on react). Using js/React (raw js interop) does it. There is actually nothing to do. You exec your js in a nashhorn thread. That gives you some html. You ship it your browser on initial GET, then initialize react on it.

This is identical to what you'd be doing on react+node. With a macro or two, it's easier than anything node provides.

As an aside, isomorphic isn't a new anything. We were rendering pages on the server, rendering updates on the server with the same templates, sticking them in xml representing jquery dom manipulation, and pipelining those in a single request since at least 2007 (when I first encountered the technique and shipped with it, I believe we used a javascript library called Taconite, maybe since 2005 from looking at the sourceforge account). Progressive enhancements were rendered off the same templates and inserted asynchronously, automatically, based on whether the controller on the server detected it was an ajax request or a bare GET. This incidentally made things very cacheable.


> React literally does this out of the box. Om does it (based on react). Reagent does it (based on react). Using js/React (raw js interop) does it. There is actually nothing to do. You exec your js in a nashhorn thread. That gives you some html. You ship it your browser on initial GET, then initialize react on it.

You're being disingenuous, I read the ClojureScript mailing list, this subject comes up regularly. People are still figuring it out, Nashorn is not well documented and the use of it for this purpose is not well documented. Please don't pretend like something is a common thing when it's not.


Do you have a link to these macros?


Here's a spot to start from: https://github.com/DomKM/omelette

EDIT: The example in the link provided builds on the now deprecated CLJX, so it's not entirely up to speed. (CLJX was the way to write clj/cljs in the same codebase until "reader conditionals" came along).


By the time JavaScript is being compiled down to WebAssembly you'll probably also be able to have the full Clojure, Scala, Java and other JVM based languages (also .Net languages) compiled down there as well.


That's going to be long time coming. To be a suitable target for higher level languages wasm is going to have to gain GC, method dispatch instructions (preferably with the sort of machinery invokeDynamic on the JVM provides, because method dispatch isn't identical across languages), dynamic code loading, threads, and probably a bunch of other stuff.

Wasm is definitely a good start, but it is only a start right now. It's a good target for AOT languages, but really not suitable for interpreted or JITed ones right now.


I'm not sure why you say that a traditionally JITed language won't benefit from this. We've had AOT compilers for the JVM and for .NET for years.

The perf may be slightly worse, but we've had good-enough perf forever.


Then we go full circle and go back to Web Forms?


I'm still waiting for stable tooling support. With Clojure 1.7, the introduction of Reader Conditionals via `.cljc` is a step in the right direction.

The tooling still isn't quite ready yet. I've tried porting some `.cljx` code over, but it's not quite working for me yet with leiningen.


Really enjoyed reading this, Jon, thanks for sharing it :-)

If nothing else it has added another unit of weight to the idea that I need to adopt CljS quickly before I am left completely behind. Now all I need is a project and more free time than I currently have... ;-)


While clojureScript is awesome and gets you to think differently when writing javascript, I think a more interesting thing people should check out it es6 (or ecmascript 6, or es 2015, w/e it's called now.). It brings many new things to javascript that people from other languages will be used to...likes the "class" syntax. Right now you can write near 100% es6 standard with a pre-compiler. Most use babel. Soon it will run on all the latest browsers without though, making it far better to write then a language that compiles to JS. JS is nice now, I know I know, just give it a try =p

Also, another thing to look at is eithe Facebook's flow or Typescript. It adds some type checking, really great. Especially if you are writing server side in Node.


'class' is one of the most commonly mentioned but least useful constructs available in ES6. Things that win out over it? Destructured assignment, sane module syntax, arrow functions, true block scope variable declaration, and constants.


Yes, but people coming from java or c# or something will like it. Despite it being just syntactical sugar. I wasn't about to list out all the benefits of es6, that would take several entire blog posts.


I would rather see ES6 with no class support whatsoever and having people learn to code without them instead of adding features to satisfy the lowest common denominator.

I've used classes in CoffeeScript and regretted it every single time. Once your web project starts to grow in scale classes quickly become your first pain point. Especially given how functional JS libraries have become nowadays.


Composition over inheritance wins, so hard.

(edit: downvote for a typically well-thought-of idiom, especially with regard to a language like js? .. if you disagree, why not talk about it?)


Classes are unavoidable in JavaScript if you care about performance. Recreating redundant functions inside a closure in performance critical code is a sure way to have slow apps.


Creating an object and creating a closure both need to allocate memory in the VM, but the closure doesn't need to expose its internals the way an object does and therefore can be further optimized by the runtime.

If you need to write performance critical JavaScript, then allocating new objects will be just as slow as creating new closures. In either cases you should allocate them ahead of time and then closures are still the clear winner.


> Creating an object and creating a closure both need to allocate memory in the VM, but the closure doesn't need to expose its internals the way an object does and therefore can be further optimized by the runtime.

Actually... creating an object instance via a constructor lets the runtime use an internal class, which improves performance (as long as you don't modify its properties post-construction). This is a well-known aspect of V8 performance.


Even with an internal class you're still doing lookups for properties. A closure can instead use local variables which are accessed by index. Why do you think its good practice to pull properties out of objects and into local variables before a tight loop?


> If you need to write performance critical JavaScript, then allocating new objects will be just as slow as creating new closures.

No, it won't. This code:

   function createThing() {
     return {
       doSomething: function(){}
     };
   }
Performs much worse (at scale) than this code:

   new Thing();
And it consumes a lot more memory since Thing.prototype.doSomething is 1 function in memory and the former is N functions.


I try to avoid OOP in my JavaScript code like the plague, I'd probably write it like this:

    function doSomething(obj){}

    var objs = [{},{},{}];
    objs.forEach(doSomething);
If I need late binding I'll use something like clojure's multi-methods. Both closures and prototypes aren't needed for this :)


Certainly.

But if object instantiation / garbage collection is your bottle neck, you should be using an object pool, anyways.

You wouldn't put _every_ object in an object pool, though - only those which obviously impact performance after identifying them as a bottleneck.

I'd hope you optimize for maintainability before you optimize for performance, otherwise you'll end up optimizing bottlenecks that don't exist.


I think the 'class' keyword is a mistake. People were happily creating class-like constructs before. But the exposed javascript "objects" made it clear it wasn't a traditional "class" found in other languages.

Also, how is ES6 more interesting than ClojureScript?


There is no single "traditional class" in other languages. Pretty much every language has its own flavor of classes with different restrictions and internals.


Perhaps a better term would be "popular"? As in, what's in use by Java and C#.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: