Why I am so excited about Clojure
technotzen.wordpress.com
technotzen.wordpress.com
(1) it's a lisp. This is 2013, compilers can deal with +-*/, I don't need to.
(2) it lacks good documentation. Most functions are documented, but badly. In particular, they lack examples; sometimes they are really tricky to use
(3) it lacks tutorials (on the main page). There is a set of pages that explain the basic concepts of clojure, such as datatypes, variables and multimethods/protocols, but they are really terse. I think Clojure assumes you already know lisp, quote, unquote, syntax trees, defs, vars, etc...
(4) it's full of magic. You can feel it, but you can't really understand it without digging through the source code.
I know OCaml, can read Haskell, and wrote a small library in closure. I still find it very hard do get around and very hard to learn.
Are you trolling? If not, care to provide concrete examples?
I've written a number of small applications in Clojure and I find that it /lacks/ magic, even in comparison to something like Python (which is generally highly un-magical). For instance, Clojure's namespaces prevent circular dependencies; while a simple example, this is idiomatic to the larger philosophy of Clojure and indicative of a general dislike of magic that permeates the language as a whole, in my experience.
(function arg arg) ; is the default form
And every form is passed to eval, which calls apply, which calls eval... until you get to a fully expanded form and the final call to eval. (map #'my-func '(1 2 3 4)) ; might eval to
(lambda () (my-func 1) (my-func 2) ...) ; which when passed to apply might result in
(list 1 4 9 16) ; which eval's to itself, a list object... 'list being a primitive
I just describe a theoretical evaluator (#'map is probably not implemented this way in most lisps). You can implement eval/apply in terms of a register machine if that makes you happy. Just read SICP for a good, basic description of one.I appreciate what the Algol-derivative languages have done and what they're useful for; but there are a large class of programming problems where telling the compiler how to solve your problem for you is far more efficient than manipulating the machine with primitives. It all boils down to that eventually and lisp-like languages simply take you to higher levels of abstractions with consistent semantics.
jp.getRawClasspath.filter(
_.getEntryKind == IClasspathEntry.CPE_SOURCE).
iterator.flatMap(entry =>
flatten(ResourcesPlugin.getWorkspace.
getRoot.findMember(entry.getPath)))
But giving informative names to the subexpressions can make things clearer for the next programmer to come along: val sources = jp.getRawClasspath.filter(
_.getEntryKind == IClasspathEntry.CPE_SOURCE)
def workspaceRoot = ResourcesPlugin.getWorkspace.getRoot
def filesOfEntry(entry: Set[File]) =
flatten(workspaceRoot.findMember(entry.getPath)
sources.iterator flatMap filesOfEntry
When to use named vals instead of subexpressions is a matter of style and judgment. From my limited and dated experience, the "one big expression" style is more common and more culturally accepted in Common Lisp than in other languages I've used. You could even call it the norm. In less expressive imperative OO languages, programmers are used to using a plethora of named variables, simply because they usually can't avoid it. In languages like Scala and Clojure, there's bound to be some culture clash when people who are used to more or fewer explicit names have to read each others' code.Here's the code I was trying to understand.
https://github.com/nakkaya/net-eval/blob/master/src/net_eval...
I'm not sure I do even now. I mean, I kinda know what different symbols and functions do, but I couldn't write it myself.
Lets look at the macro, once you understand the basic macro concepts, witch are actually quite simple but still hard to understand. Its like a normal function, exept that the function code will be added to the var as data.
But the salient point here is there's really nothing magical about what's happening there.
Of course, the power of Clojure is that you actually can express this concept in the language. RMI looks pretty ugly by comparison.
It decimates your hiring pool--but the programmers who are fluent in Clojure or other Lisps tend to be skilled. I also think Clojure is more concise and more productive than, say, Java--which reduces the volume of code, and lets you do more with fewer people. Keeping the team small reduces the number of meetings and managers, and keeping the codebase small makes it easier to understand and maintain.
YMMV, naturally--but I wouldn't consider these concerns as insurmountable obstacles to using the language in production.
As for the reasons I use it, it has great development tools, a good amount of libraries, Java interop (a big one), and it's just a well designed language.
On the other hand, there's an amazing focus on doing the right thing rather than throwing features at a wall, which I like immensely. Sadly, long lists of new features seems to drive adoption. :(
I don't understand what you mean here, the lack of infix operators in Lisp? You make it sound like prefix notation is inferior. But given how Lispers usually sell it as the best thing since sliced bread, such reactions don't surprise me.
Anyway, you're right. It really seems like C-style syntax has won, and deviating from that is certainly a barrier of adoption. Clojure has been remarkably successful despite this, but I really don't see it becoming the next Java.
At least I've personally found that doing linear algebra, physics calculations or anything with more complex equations in Lisp-like languages is a huge pain.
(4) it's full of very reasoned data structures and designs, like, e.g. HAMT, transients. You can write dense/nested functions, and people do, and yes, other people have problems with it, see https://olabini.com/blog/2012/08/6-months-with-clojure/
(5) Being a haskeller/ocamler I thought you were going to make a type system argument, which is a valid argument, liek this blogger i saw yesterday http://failex.blogspot.com/
The s-exp notation is actually more* programmer friendly because when you're using a decent editor you can work with code at structural level.
When I work in Clojure I'm not thinking in term of manipulating lines. I think in terms of expressions. I want to take this expression and parent it here or there, I do that. I want to factor out a piece of logic I can select the block and move it out, etc.
This also facilitates the powerful macro system where I can trivially write code that templates code for me or create DSLs to express the particular problem domain I'm working on. The whole aversion to prefix notation is incredibly superficial.
>it lacks good documentation. Most functions are documented, but badly. In particular, they lack examples; sometimes they are really tricky to use
This is simply false. There's excellent documentation available at
http://clojuredocs.org/quickref/Clojure%20Core
and
http://clojure-doc.org/articles/content.html#clojure_languag...
with lots of examples for each function, tutorials, and guides. Furthermore, there's tons of traditional documentation available in form of books.
>it's full of magic. You can feel it, but you can't really understand it without digging through the source code.
It's quite the opposite in my experience.
>I know OCaml, can read Haskell, and wrote a small library in closure. I still find it very hard do get around and very hard to learn.
I find Haskell is much more difficult to read than Clojure. Perhaps it has something to do with familiarity as opposed to any inherent difficulty?
Lips has just a really tiny (if any) advantage over other languages in this. I can move code around quite easily in Java. And I don't have to care about formatting (I use autoformatter). In Lisps, formatting code manually is needed and it's a bit of a PITA especially when changing the code.
This also facilitates the powerful macro system where I can trivially write code that templates code for me or create DSLs to express the particular problem domain I'm working on. The whole aversion to prefix notation is incredibly superficial.
Usefulness of macros is overrated. In my experience, the s-exp syntax is too high price for macros. I like Julia's approach to macros much more.
I love that s-exps are totally unambiguous and find them easy to read personally.
I'd love to see a stream-lined Dylan-like language that targets the JVM or CLR.
I don't find it to be the same at all in practice. Lisp has a huge advantage in this because the code is written by manipulating the AST. You see the tree and the branches of executions visually. So, I can say I want to move this node to that position, or extract this node into a separate function.
I find it's like playing with lego. You just stick individual pieces of logic together to produces complex functionality.
You simply can't do this in Java on any practical level in my experience. It also doesn't help that Java code is imperative so even if you selected a block of logic, it doesn't mean you can just move it elsewhere without any side effects.
>Usefulness of macros is overrated. In my experience, the s-exp syntax is too high price for macros. I like Julia's approach to macros much more.
I strongly disagree, I find macros are incredibly useful. Clearly most people agree as some sort of a macro system creeps up into pretty much every language.
However, most languages don't allow you to apply the language to itself when templating code. So you end up with special crufty syntax that eventually becomes a whole separate language that you have to learn.
I'm not sure what price you're talking about either. I actually prefer s-exps to ALGOL style syntax. With s-exps your code is very regular and it follows the principle of least astonishment much better than alternatives.
There are no inherent downsides to the syntax, if anything it makes the interaction between pieces of code more visually apparent. It provides extra visual information about the structure of the code. I personally like that very much.
1. The minimal syntax makes it harder to read than more traditional languages.
2. It's uncomfortable to do imperative or object-oriented programming in Clojure. (Yes, many problems are easier to express in other than the functional paradigm.)
3. Using state is not a priori wrong but it's difficult in Clojure.
4. The parentheses are sometimes annoying, especially when I want to quickly test something in the REPL.
Some lispers (like Paul Graham) believe in something like "macros make lisp the most productive language on Earth, at least for the top x % programmers". From my experince, this is just wishful thinking. It makes them feel special and better than others.
That's an incredibly cynical view. I'm sorry that Clojure was not for you -- it happens. People have different ways of thinking and the language that makes sense to you might not make sense to me. This is natural I would say and not likely reflective of general intelligence. There's no need to be bitter about it.
> People have different ways of thinking and the language that makes sense to you might not make sense to me. This is natural I would say and not likely reflective of general intelligence. There's no need to be bitter about it.
I was mostly refering to the essay by Paul Graham that is sometimes referenced here on HN. I find some of PG's claims about lisp's productivity ridiculous and almost religious.
EDIT: okay, I got downvoted for some reason. Care to explain why?
The mantra in Clojure is "don't write macros until you NEED macros" (or some alternative[1]). They make things horribly complicated and are awful to debug and make code that uses them hard to debug too... especially within a JVM environment (your code gets translated twice).
[1] http://clojurefun.wordpress.com/2013/01/09/when-do-you-need-...
To put an analogy: people would've disgusted if you used a life jacket for no good reason, but they're handy when you really need them :)
I also like Lisp syntax regardless of macros, mainly because it's simple, consistent and prefix notation is really handy. The S-expr abstraction IS useful when dealing with code blocks (see https://news.ycombinator.com/item?id=5940620)
Yes, but we're in a thread dedicated to Clojure ;)
> "Macros make things horribly complicated" is nonsense, or no skilled programmer would use them.
Which is what happens, really, and when used it's in a very limited fashion. For example, for quite popular projects inside the Clojure community: Leiningen used one macro[1] and Compojure two[2].
A properly done (and properly used) macro might not make things complicated, but this leads me to the next paragraph.
> ease of debugging is an issue quite apart from anything to do with macros.
It's usually hard, but macros make it HORRIBLE since you can easily lost track of the generated code. Like if translating from Clojure to Java Stack Traces wasn't hard enough...
Whenever you use a macro, the stack traces you receive from the code using it might not like like what you expect at all. Macros are bad because they mutate your code. You usually have to expand the macro and debug there instead of just looking at your damn code.
The big problem is not macros, but code which uses macros.
[1] https://github.com/technomancy/leiningen/search?q=defmacro&r... [2]https://github.com/weavejester/compojure/search?q=defmacro&r...
Also, these comments seem odd:
A properly done (and properly used) macro
The big problem is not macros, but code which uses macros.
The macros I know are effectively impossible to misuse. They tell you how they're supposed to be used and you just do it. There's not a lot of room to go wrong! Can you give an example of a macro which is hard to use properly?
I do that using functions :)
One of the biggest Lisp proponents (forgot his name) when joining Google found out that other good developers using other languages were just as productive.
I guess while I'm here, my feelings on the other points: 2) good, it's a functional language 3) Clojure's state management is excellent, discouraging mutable state is a good thing. 4) the reply highlights the matching parens when you close them, it hasn't been much of a problem for me
3) Sometimes mutable state is the best way to go. I'm not in the "mutable state is wrong" religion :)
When you use mutable state, you're creating a model that essentially ignores time. Sometimes this is a useful omission when performance is required, but time is so integral to our Universe it's hard to remove it from a model without unforeseen consequences.
I'm not sure what you mean by saying that mutable state ignores time. Real world applications have state, you can't avoid it.
Let's say you observe the state of a lightbulb. You might say "The lightbulb is on," but the lightbulb could be turned off, rendering your statement technically invalid. So instead you might say, "The lightbulb is on, now", but even that's not necessarily true, as in the time it took the light to reach your eyes, the lightbulb could have been turned off. So the most accurate description you could give would be "The lightbulb was on, 10 nanoseconds ago."
Systems with mutable state have no explicit time element. So "x = 1" is analogous to saying "The lightbulb is on." Systems with immutable state have to be more specific about time, so they might say "x[when t=0] = 1". Can you see how this is a more accurate representation?
Mutability is really only useful under the following circumstances:
1. You need performance. 2. You have only one thread. 3. You are performing no I/O.
In Java, I can very easily choose between mutability and immutability. If I put "final" in the variable declaration, the variable is immutable. So what I usually do is default to immutability but opt out if needed. Which is very often, usually because 1) it would make the code more elegant and easier to understand 2) for performance reasons.
You are performing no I/O.
Why does I/O make mutability useless?
Mutable OOP presents the fiction that you can retrieve the current value of a property or object, but we know this isn't true. In reality, all we can do is to find a past value of a property, because there's always some latency involved in reading. If it's a single value, maybe the latency is only a few nanoseconds. If it's a lookup against a hashtable, perhaps we're talking microseconds. If we need to access I/O, our latency increases to milliseconds or higher.
The more concurrency and latency in a system, the harder it is to maintain the fiction that latency does not exist. It's worth asking whether a model that falls apart so quickly (which it does whenever you need a synchronized method or data structure) is actually useful to have in the first place.
Java does allow variables to be marked as being immutable using the final keyword, but it doesn't have very good tools for dealing with immutable data. It doesn't have efficient immutable data structures in its core language and it has no tail call optimisation, or even a pseudo-TCO structure like Clojure's loop/recur. In short, it's much more difficult to use immutable data in Java than it is in a functional language like Clojure.
Java does allow variables to be marked as being immutable using the final keyword, but it doesn't have very good tools for dealing with immutable data. It doesn't have efficient immutable data structures in its core language and it has no tail call optimisation, or even a pseudo-TCO structure like Clojure's loop/recur. In short, it's much more difficult to use immutable data in Java than it is in a functional language like Clojure.
Mostly agree, functional languages like Clojure are definitely more immutable-friendly.
I guess Java does make it seem like the opposite is the case; that it's easier to work with mutable data, and that immutability is just a needless restriction. However, in languages with lambdas and higher-level functions, local mutability is rarely required, and becomes a hindrance rather than a help. Just look at how many times "options.dup" turns up in Ruby code: https://github.com/search?q=options.dup&ref=cmdform&type=Cod... . It's an annoying pattern in Ruby to work around the lack of immutable maps in the core language.
I agree on three though, and I think the way Clojure handles mutable state is excellent, but it's a good thing that it's not trivial to just say x = 5, x++.
Rich's philosophy on this is "mutable code isn't needed most of the time." It's a very different argument.
As for (2), if by "real world problems" you mean "commonly occurring, trivial, day to day problems", then yes, I also solve "real world problems" every day with clojure.
>1. The minimal syntax makes it harder to read than more traditional languages.
I personally find that the minimal syntax makes it much easier to read the code.
The more syntax the language has the more of it you have to keep in your head when reading code. Different language features might interact in unexpected ways, and so on. This is mental overhead that I don't need to worry about when the syntax is regular.
>2. It's uncomfortable to do imperative or object-oriented programming in Clojure. (Yes, many problems are easier to express in other than the functional paradigm.)
Could this stem from the fact that you're likely much more familiar with OO and you've spent years internalizing OO patterns for solving problems.
I find that for majority of problems I deal with functional solutions tend to be simpler, cleaner, and more reusable.
OO on the other hand is directly at odds with reuse because you marry logic and data together into classes. If you write a method and you need to use it for a different problem, you often have to jump through hoops to do it.
On top of it OO encourages premature classification. If you create a class and you need to use that data in a different way later you have to translate it in some way. This is why you have things like wrapper and adapter patterns.
This problem simply doesn't exist in functional code. You simply group functions into a namespace that has same organizational benefits as a class. A namespace can represent a specific domain, but you can easily pass the output of a function from one namespace to a function in a different namespace.
>4. The parentheses are sometimes annoying, especially when I want to quickly test something in the REPL.
There's a lot less control characters in Clojure than say in Java. If you count all your parens, curly brackets, semicolons, commas, and so a language like Java has far more noise in it. There are very few languages that have cleaner significantly syntax in my opinion.
Also, if you're using a proper editor you rarely have to deal with something like balancing parens by hand.
>From my experince, this is just wishful thinking.
From my experience, actually having worked with Clojure production systems for a few years, now macros can be incredibly helpful in expressing problems cleanly and removing boilerplate.
This can't be emphasized enough. I never understood why so many people thought that putting methods and data together was a good idea.
I think Rich Hickey in an interview with Stuart Halloway possibly once said that when you jam your methods in with your data you're essentially creating a mini-dsl that makes reuse impossible. I can't agree more.
Now, of (1)-(3), the only one which has the hope of backing up your point is (1). Why should Clojure not having good documentation right now be a reason Clojure will never be successful? Why should Clojure not having tutorials right now be a reason Clojure will never be successful? It doesn't make sense. What if those "facts" change?
Modern Lisps use homoiconicity not because it is easier for the compiler, but because it is easier for the human. In languages with syntactic macros, (as opposed to string-interpolating macros), one manipulates the program's AST directly as a data structure. Making the code's AST regular, predictable, and explicit facilitates code transformation, which is an integral part of programming in a Lisp dialect.
2, 3) There is tons of material on Clojure. Read a book or two, google for christ's sake to get live examples on stackoverflow and hackers' blogs. Also great features are (doc fname) and (source fname) to get source right away without even leaving your REPL.
4) It's very subjective what you wrote, so it can't be falsified.
That said, the two big "strikes" against clojure for "mainstream" adoption are as you pointed out, it's a Lisp, and it's dynamically typed.
I like the core concepts of Clojure. That there are a small set of primitives that have a uniform interface and how Clojure is anti-OO. Clojure actually does OO better than OO languages do, but that's another story.
If I could just get a Clojure with some optional typing, a python-like syntax, and awesome tools, I'd be a happy camper.
There is mori http://swannodette.github.io/mori/#mori for persistent data structures.
Callbacks are handled by Promises or say async https://github.com/caolan/async
For heavy compute tasks you can launch child processes under Node.js and communicate with one management process, the Cluster http://nodejs.org/docs/latest/api/cluster.html lib is experimental as of now.
Even after decades there are still people who use Lisp-like languages and who find them fascinating and just right tools for their job. I, for example, am a huge fan of Common Lisp and I'm really glad to see new stuff happening around it and new people discovering it because there were times I was a bit afraid about its future.
But will it ever dominate or explode? No, it won't. Same with any other Lisp. And it's okay.
I only ask because the whole idea of using it for "Big Data" flies right out the window if it's significantly slower than plain old Java. Especially if it's slower using naive or expected Clojure methodology. And if there's not a speed advantage, than companies can find a lot more people who know and can work Java code than Clojure.
Clojure has very nice concurrency mechanisms baked right into the language.
That's a very strong claim, and I've never heard anyone make it before. LuaJIT is unbelievably fast. I'd be extremely curious to see the proof.
(As a side note, on some level it's hard for me to accept that Clojure is fast because using it feels gratingly slow — since all the tools take several seconds to do anything thanks to the JVM's startup time. `lein repl`: 4 seconds wait. `luajit`, or `python` for that matter: utterly instant.)
I have been frustrated with Clojure lately because of startup time (I do a lot of CLI tools), and would love to use Luajit, but my coworkers hate when I write in languages other than Ruby or Clojure. For my own pet projects it is great.
Ruby and Python are incredibly popular despite being incredibly slow. Clojure has decent enough performance, plus easy parallelism/concurrency...
And that's also why I asked about whether naive Clojure script is performant, or whether you have to take so many non-obvious routes to eek out the performance that it loses "conciseness" as a point in its favor.
(Disclaimer: I don't have recent performance numbers on Java vs Clojure; that's why I was asking for them. The double/quadruple numbers above were pulled from thin air.)
Unfortunately, I can't find good examples of modern performant clojure with benchmarks at the moment. As far as I understand, the alioth benchmarks are still out of date.
I have one system where clojure performs better than java. It's not an apples-to-apples comparison as the java source is very rigid and stateful. There's a ton of recalculations being done and there's almost no way to thread it out because the current implementation relies heavily on mutation. The clojure equivalent is much smaller and just overpowers the java implementation due to the ease of threading (pmap, memoize). In that specific example I was looking at maybe 20x performance increase?
I have another test where I cannot even get close to java performance. Even after adding in type specific checks. In that example java wins because it's a native/primitive java implementation. Even without threading the java side wins because it's been reduced to such a simplistic operation (500 lines of java code using only primitive types) that the overhead of clojure can't beat it. In this test java is about 5x fastar than the clojure equivalent.
It really depends on what you are doing I tend to think of it like raw java > clojure > over engineered java... In some instances it can be very, very powerful.
Scala > F# > clojure > Haskell (really bummed about the last one!)
In London finance circles. Does that sound about right?
But tbh, if you want a Clojure job, it wouldn't hurt to go to the clojure meetings at SkillsMatter. With all of that said, the market depth does worry me, especially for finance.
We still need to organize our code tho, even with a functional language... and I have missed the abstraction of OO (Using node.js)
While cool,but really, Is there such a great clamoring for scaling programs over multiple cores ? I never hear anyone asking about it job postings. May be I am working in the wrong part of the industry than those mentioned in the blog post. But I rarely hear game programmers talking about clojure/ functional programming. Most popular clojure projects on github are web frameworks. I am puzzled why clojure is so popular among web developers if concurrency over multiple cores is its 'killer' application.
From what I remember this paper never mentions 'concurrency' as to 'why functional programming matters'
http://www.cs.utexas.edu/~shmat/courses/cs345/whyfp.pdf
Neither does this( the only one?? ) poster child for lisp's success in wild talk about concurrency http://www.paulgraham.com/icad.html
I think the whole multiple core thing is over blown in association with functional programming. I think it would be pretty misguided for someone to adopt a functional programming with multiple cores in mind.
Hearing what? That pmap is a drop-in for map giving instant speed gains? That's odd. I've never heard that. Like anything pmap has its tradeoffs.
> poster child for lisp's success
You're conflating "functional programming" with Lisp.
> I think the whole multiple core thing is over blown
That's something that I would probably agree with. However, people tend to focus on that regarding Clojure because it provides more than one model for describing concurrent state changes. People get excited about that I suppose.
That was just an example of how programming without state makes it easy to scale it over multiple cores.
> Like anything pmap has its tradeoffs.
No one said anything about pmap being a drop in replacement for map. If pmap didnt have tradeoffs there wouldnt be a 'map' and just pmap.Common Sense. I am not sure why you are even mentioning that. As I said that was just an example of ease of writing multithreaded programs in clojure. Which was one of the main points in the blog post. Did you get a chance to read the blog linked to this post?
* New programming practices are adapted after the mainstream programming industry has adopted them.
* Java is not widely used, partially because when the great Java enterprise switch happened, game studios were still debating if switching to C++ was worth it.
* Because games deal with rapid state changes, switching from relatively intuitive object-oriented designs to functional designs requires a rethink of how most game engines operate.
* If it doesn't work on the consoles, the mainstream industry is much less likely to use it. Java isn't natively supported, and Microsoft is unlikely to add anything to the XBox to make it easier.
* Most games are still single-threaded 32-bit Windows applications interfacing with DirectX.
http://www.st.cs.uni-saarland.de/edu/seminare/2005/advanced-...
Porting a 20 year old game for fun in Haskell doesn't mean that Haskell is ready for the cutting edge of modern games.
The plain fact that important personalities in the AAA games industry are willing to spend their valuable time coding something in Haskell instead of doing something else, means a lot.
For example, are you aware that quite a few studios are now using Erlang for their MMO servers?
Absolutely. Queues, databases, caches, machine learning, graph algorithms, CRDTs, image, audio, and video processing, stream algorithms, analytics, geospatial work, even HTTP APIs: all demand compute performance. Since CPU flops have been essentially stagnant for ten years, the only way to improve performance on commodity hardware is with parallelism. Almost every program I've worked on in the last five years has demanded multicore programming, or at least in-process concurrency.
Clojure is not the fastest language out there, but it does make reasoning about concurrent code dramatically simpler than other languages. My Clojure programs tend to parallelize trivially over 16 or 32 cores, and only rarely contain race conditions, deadlocks, or other threading bugs. In contrast, I routinely struggle to write correct multithreaded code in Java, and when I do, I usually adopt a slower locking mechanism because I'm just not smart enough to reason about concurrent mutable state.
Why is Clojure better for writing concurrent programs? For one, it's multi-paradigm. You can serialize transformations over state using normal JVM locks, agents, atoms, refs, or promises. Immutable shared-structure objects make concurrency safety trivial--but Clojure's identity types make reasoning about state easy, instead of having to express everything through monadic composition. For mutable state, you've got java.util.concurrent and Cliff Click's high_scale_lib available, plus great libraries like Netty. It's a deeply pragmatic language where the defaults are safe, but controlled speed is available where you need it.
Or you could run 64 Unicorn/V8 workers per node, and push all the hard problems into the database. That's a totally valid strategy--but I think there's a little more to life than that. ;-)
The multiple core thing, it not overblown. Clock speed scaling ended a few years ago. Single thread performance scaling is dead, and we need a paradigm shift to deal with the multi-core future. Intel MIC has 80 cores and it is only the beginning. We need new tools to handle this new level of parallelism. It’s likely that some form of functional, flow-Based, or reactive programming will emerge as the tool of choice in this coming era.
"OO design patterns such as MVC are going nowhere." Really? MVC is going nowhere? And how is functional organizing UI and model data better?
You can promote a technology without trashing another one. People know what functional is and it has its niche as with any other things.
To your other points - Clojure does data great - much nicer than OO languages I've used. As far organizing UIs better Clojure programmers adopt many of the same patterns that are currently en vogue. However I think there are some more interesting new techniques just around the corner and we will be hearing about them soon enough.
That said, if you subscribe to the assumption that good software design is about separating a system into discrete elements of functionality, then the functional model is generally preferable over the OO model. In OO languages, unrelated concepts such as polymorphism, encapsulation, namespacing, inheritance and (often) mutable state are combined together to produce classes and objects. In functional languages, these concepts are generally kept separate.
Of course, if you want to coerce the word "productivity" to mean "making boring CRUD webapps quickly", you have a point.
Plus ça change, plus c'est la même chose...
Oh and books with code listings to type in hexadecimal rows of opcodes. :)
I'm not saying I'm convinced a Lisp-like will explode, much less that it'll be Clojure in particular, and I do think it important to keep the history in mind, but I think you overstated things.
Many of the capabilities of modern IDEs were already available in Lisp and Smaltalk environments in the early 80's, but you could buy a house with the price of those systems.
Though they are more and more 'native' clojure libraries being released.
I don't think it will ever get more than a 2% share in the software world, but I think it can get the right 2 percent. At least, that's what I hope will happen. I also think that it will live (possibly even surviving the JVM) for a long time.
There will always be detractors. But then again, you can't teach a dog math.
I spent a tiny amount of time getting to know Clojure. I liked what I saw, but some things confused me due to lack of looking into it/thinking about it. I'll need to spend more time with it to find out if I'm a dog. ;)
...you did... what?