Wow, lots of questions. I am exhausted but will do my best to provide an initial answer.

> impossible to debug efficiently without a) understanding everything around it and b) printing everything. Debug statements seem to "ruin the cleanliness" (as well as genuinely ruining threading macro flows.

I've never once had to add a debug statement to my Clojure code, not sure what you are doing honestly. You can easily debug with Emacs + Cider which allows setting breakpoints, inspecting, and evaluating forms while debugging. This is much more than debuggers in many languages. Further, you can also use Cursive + IntelliJ which gives you pretty much the same thing, only more like most people who have done Java, C++, or C# are used to in the various associated IDEs such as IntelliJ, Eclipse, Visual Studio, (or Emacs/Vim for that matter) etc. Given the data you are dealing with most of the time is immutable, things couldn't be clear IMO.

The only time I find myself printing things is in the REPL. A few years ago I did this more often in Chrome in ClojureScript, which mostly goes away now with one or more of nREPL, Nightlight, Figwheel (or the many similar libraries). In fact I'd say the debugging situation here is better than most languages because you can instant eval things as well as live code, and see those changes immediately in the browser.

Regarding threading macros, I assume you're talking about (->, ->>, ->as, and so on). Again, you can just eval these partially in the debugger, and worst case, bind something to a value you set in the debug session as you would in a plain REPL session. I would agree these are harder to step through. If for some reason you meant macros in general, I'll repeat what I always say to new Clojure and Lisp users in general - do not write macros at the start, and when you do, question the reasons why you are doing so. Macros are insanely useful and powerful when you need them, but most of the time you do not for the average app (obviously many exceptions). Worst case, you can macro expand, paste that, and debug or debug the macro expand in an debug eval.

Overall, I've found debugging to be substantially less pleasant in most languages that are popular such as Python and Ruby vs. Clojure but less pleasant than say Smalltalk or a Lisp machine. Like many languages, the situation with Clojure improves over time. People complain about the stack traces but most of the time they don't bother me and each version has improved on that. I came from the assembler, C, Fortran, Lisp world, so in some ways that has made me more keen how to write code that is easy to debug and to not fear debugging.

> Do other companies use Clojure for non trivial web applications? Have these Clojurians ever worked on a properly complex system? A lot seem to do just data analysis with Clojure. More importantly, have they ever worked on a properly complex system that they haven't been involved with from the start where debugging comes back to 'intuition' and 'whack a mole' type debugging?

Yes, there are various lists out there if you Google some. A brief list: Amazon, Netflix, Pivotal, Walmart, Heroku, Factual, Capital One, Roomkey, Spotify, Soundcloud, the list goes on. I think it's fair to say at least one has a complex app and at least one is a not for data analysis. Clojure is quite often used at very large companies that are almost surely building systems more complex than yours (no offense, just basic probability). Saying Clojure seems to be used mostly for data analysis and therefore implying it might not be good for web apps is like saying that about Python, which in fact is used more than Clojure for data analysis.

Regarding, web applications, by nature they are trivial compared to many domains. Of course you can make things complicated by adding a lot of moving parts, but these things are usually complimentary to a web app (ex: stream processors like Spark, Storm, Google Dataflow). You can also make things more complex than they need to be by bolting on frameworks and trying to shoehorn your business and code concerns into it. This is one reason some people like lighter frameworks for some purposes and heavier for others (see Django vs. Flask for instance). Clojure generally spurns heavy frameworks for web stuff because functional programming tends to encourage or even require composition. As such, things already fit together and simply picking well-tested libraries to form your "stack" tends to let you use the right tool for the job more readily. Obviously this is somewhat subjective, but I think other people who insist on heavy frameworks have something to learn here. If their framework was so awesome, we would not need 10 more next week, and yet that is what happens.

Regarding "intuition" and "whack-a-mole" debugging, I would agree that the former is important, while the latter is a sign you've done something terribly wrong. Clojure like many functional or data-first languages tends to push you towards certain tracks that should really not lead you to whack-a-mole debugging. The idea of immutability by default and functional composition in part is that it is harder to screw up your state. This should make debugging very clear at runtime since you can quite often literally dump your entire state and have quite high visibility into what is happening in your application. A good example of this WRT web dev as you mention is ClojureScript (yes, not Clojure but same principle applies) and ReFrame or Om-Next. You have a single representation of your state as an immutable database that you update instead of things scattered about, meaning you can inspect it, query it, access it across threads (if it was on the server), etc. In Clojure and many languages, you need to think in terms of operating on data structures not classes, objects, or potential language construct distractions. This again drives away distractions while debugging that leads to shots in the dark. This of course should feed your intuition too in that if you see something with a weird state, you did something wrong like reset! instead of swap! or used mutability or you're just understanding your own code wrong.

It's not really fair to compare, but like I said, I find the debugging situation to be excellent. The fact that you can also live code with the browser, work directly in a REPL session (I open them for days), and so on means you can potentially write and test your code easily at the same time. This is somewhat like TDD, but instead of just writing a unit test, you actually run the code and get more immediate iteration and feedback. Of course you can still do test-first TDD too and eval those and even run the tests in the REPL. There are some traps here like stupid things you can do in the REPL, but there are many libraries to help you solve this that promote practices that are good regardless of the REPL (ex: Component, Mount).

I'm already writing too much, so I'll say with regard to what Rich says, just read Clojure news groups and JIRA and such. He has said many times Clojure is essentially a pragmatic balance of some of the super powers of Lisp with the practicality but limitations of the JVM. Do you want a perfect language or one that helps you get work done today but maybe better than a lot of what is out there? Moreover, do you want a language you can use in reality or just academia? Clojure solves that via the JVM and a huge existing ecosystem.

Anyway, feel free to ask more and good luck. I am sorry if I sound harsh, but I am trying to give you real answers rather than fluff.