31 ms·
Clojure: All grown up
- michaelochurch 14y agoClojure's great. While I like static typing in general, I see a better chance of long-term success in Clojure over Scala. With Scala, there's nothing wrong with the language, but the amount of Java-in-Scala code I've seen has convinced me that there's unintended cultural risk-- at least in the enterprise, where software has been done wrong for decades-- while Clojure forces people to be exposed to new ways of doing things.
- pjmlp 14y agoScala and Clojure only work if you have top developers on your team. Given my experience on international enterprise projects I think: - static languages win over dynamic ones, because most teams only write tests if obligied to do so, and even then most tests aren't proper. At least it makes sure the code is in a compiled state. - most developers on the teams are google-copy-paste monkeys that only have basic understanding of Java/C#/VB so they need similar enough syntax to do the transition to new languages.
- vmind 14y agoThere's some progress being made on static typing in Clojure, too: https://github.com/clojure/core.typed https://github.com/clojure/core.typed Still fairly early days on that though (missing protocols and rest parameters are the big issues I think)
- weareconvo 14y agoI tried switching to Clojure, and while I love the purity, simplicity, and logic of it, two things always bothered me: 1) Immutable data structures are always going to be slower than their mutable cousins. 2) "Clojure code is beautiful" should be changed to "Your OWN Clojure code is beautiful". When I finished writing a compact piece of logic or data transformation, I was often struck with the beauty of it. When I tried to read someone ELSE's Clojure code, however, I couldn't even begin to make sense of it. I am ever open to being proved wrong, however. Any Clojure programmers reading this, please reply with some code that is readable, elegant, and performant, to provide a counterpoint to my pessimism.
- lukev 14y agoAs someone who has breathed Clojure for the past three years, I very rarely come across code that is truly difficult to understand. It does tend to be more information-dense than other languages (especially Java) but that just means I only have to understand a couple hundred lines split into 3 files instead of thousands of lines across dozens of files. That said, there is definitely some nasty Clojure code out there, but I'm not sure that's avoidable in any language. Fortunately, the conventional wisdom to only use macros when necessary has started to catch on and that's made the situation a good deal better.
- weareconvo 14y ago> As someone who has breathed Clojure for the past three years, I very rarely come across code that is truly difficult to understand. I'm not really arguing that Clojure code is "truly" difficult to understand, if that is taken to mean reasoning about its performance and effects. Rather, I'm talking about the fact that idiomatic Clojure code encourages writing functions upon functions upon functions, which continually builds up layers of abstraction that inherently make code more and more difficult to read. Example: console.log("Hiya."); console.log("How's it "); console.log("going?"); vs. printFirstString(); printSecondString(); printThirdString(); function printFirstString() { ...etc }
- lukev 14y agoI don't know anyone who writes code like that. Unnecessary wrapping of functions is an antipattern. Idomatic Clojure for what you just wrote is: (println "Hiya.") (println "How's it ") (println "going?") If a Clojureist wanted to get fancy and build an abstraction (as they probably would) they'd probably write a debug function instead of using 'println' directly: (log/debug "Hiya.") (log/debug "How's it ") Which is, granted, an abstraction, but isn't any harder to read.
- vorg 14y agoOr define a function called `printlns`. Then call... (printlns "Hiya." "How's it " "going?")
- lkrubner 14y agoThis is very true: "Leiningen and Cake, joined forces to become an all-powerful build tool. Then Leiningen reached version 2. (And let me tell you, Leiningen 2 alone makes Clojure worth using.)" Other build tools, and package managers, such as "bundler" in the Ruby world, seem pretty weak compared to Leiningen. This is a very powerful tool. The tooling and the eco-system are reaching a very powerful level. For now, I use Emacs as my editor, but I am waiting for LightTable ( http://www.chris-granger.com/2012/11/05/meet-the-new-light-table/ http://www.chris-granger.com/2012/11/05/meet-the-new-light-t... ) to get just a little further, and then I intend to switch to it. This whole article is good, but this is the part that gets to the heart of the matter: "Rubyists know that their language effectively got rid of for loops. In the same way, Clojure gets rid of imperative iteration in favor of declaration. Your thoughts shift away from place-oriented constructs like memory and gravitate to data structures and functions like map, reduce and filter. Your “class hierarchy” turns out to be a type system that happens to also lock away well-meaning functions into dark dungeons (more on that in another article), and getting away from that is freeing." That might be the best summary of the strengths of Clojure: it helps you think about data structures and transformation, rather than thinking about the ceremonial and imperative code that your language needs to hear.
- DigitalJack 14y agoI'm a big fan of Clojure, but I don't think I'd ever write an article like this. I guess I must not be an evangelist at heart...I will tell people that I like something, but I never tell them that they must use it. You know yourself far better than I know you, and so why would I presume to tell you how to live your life? Functional programming is sometimes great. Most forms of programming are sometimes great. But I don't think there is one form that is great all the time. Maybe there is, and maybe if I come across it I'll be smart enough to recognize it... but in the mean time, I'll just try to use what makes sense to me. And sometimes, functional programming just doesn't make sense to me. I still can't quite get my head around monads. They have just one or two too many levels of abstraction for me to hold in my head. I think I'm almost there, and was trying very hard to grasp them, but then in one of the videos I was watching, the guy said this: "Monads are a solution to a problem you will never have." He said it in jest, partly because the language at hand was Javascript, but it really stuck out to me. Clojure has what I would call "sensible" state containment via STM. And sometimes just plain storing some state is the easiest and most straight forward way to go. I love working in Clojure because it makes it so easy to break down problems into bite sized functions. That, and the concision of the syntax suits me. I'm trying to accomplish the same thing in Java by having some classes that I treat as a namespace and load them up with static functions in that namespace. I'm sure a lot of people would spontaneously barf on their screen if they saw my code though.
- weareconvo 14y ago> I'm sure a lot of people would spontaneously barf on their screen if they saw my code though. This is exactly the problem I had. My canonical "getting to know your new language" project is always writing a simple chess engine. After writing a few of the high-level constructs, my next step was to try to browse some other .clj libraries, because I was pretty certain that a lot of the tedious tasks involved in writing a chess engine had already been solved. After reading their code, I very quickly gave up.
- tikhonj 14y agoMeh. I personally find articles like this useful: that's how I was turned onto all the technologies I really love right now like Linux, Emacs and Haskell. Most importantly, I was convinced to work through the learning curves for all of these--which were all easier than reputed but still took some effort--which turned out to be more than worth it. Basically, the reader can decide for themselves. Also, each reader reads more then one blog post. So having a bunch of extreme opinions to compare (e.g. a strong case for a bunch of different languages) is more useful than a whole bunch of hedged blog posts that all repeat the same refrain: "well, all languages are basically equal and you should use what seems best". In fact, blog posts like that are a big waste of time. (I'm looking at you, prog21.) I would much rather hear a bunch of different, reasoned opinions--especially if they contradict each other--than hearing the same boring, condescending tripe about choosing "the right tool for the right job" over and over. Also, I think the idea that all--or even most--programming languages are somehow equal is patently absurd. Similarly, I think the oft-reused tool analogy is deeply flawed. But that's neither here not there and enough material for a blog post of its own. Of course, that's something of a false dichotomy, although it does come up in practice. But I think posts advocating a technology are also good by themselves. The choice of technology may be subtle, but this post only needs to present one option, which it does admirably.
- pbiggar 14y agoTotally agree. We built a PaaS entirely in Clojure (https://circleci.com https://circleci.com) and its absolutely a grown-up language. I was unsure when we started (my cofounder has been using Clojure since 2008 and was adamant that this was a good idea), but Clojure makes it very easy to write big hardcore systems. Definitely one of our competitive advantages.
- mjt0229 14y agoI take this as an extremely positive indication - that someone can be skeptical and won over after having built a substantial system. Virtually every time I look at a shiny new technology, even ones I profess to like, I like it substantially less after I've been using it for some time and know where its faults lie.
- pbiggar 14y agoI've now been writing clojure for 18 months, and its definitely my least-hated language (python is a distant 2nd, coffeescript a distant 3rd).
- dschiptsov 14y agoSounds good when you know nothing but Java and never heard of CL - knew nothing about, say (disassemble #'foo) or what is FFI etc. This is also very telling - lets you deploy your Clojure Web app to a JBoss server and take advantage of JBoss’s scalability without any XML configuration. You get a mature enterprise-ready Java server without the pain of Java or of configuration. I wonder how many orders of magnitude difference in "scalability" we would see with a simple nginx -> fastcgi -> sbcl setup.) Memory usage under long periods of time with pending storage/back-end calls is also interesting topic - how JVM blows up just after few hours in "production".)
- pjmlp 14y agoThe main issue is that Clojure happens to be more enterprise friendly than traditional Lisps. It is easier to give a jar to the devops team, than trying to convince them to add support for yet another language the crazy developers are now trying to use.
- lukev 14y agoThat's unnecessarily dismissive. CL is a wonderful language, but it's gathered a lot of cruft over the years and essential features like multithreading are not standardized. More importantly, it doesn't have a focus on immutability and functional programming by default. I'm not even sure what you mean about the JVM blowing up after a few hours... Tuned correctly it'll stay up indefinitely.
- sedachv 14y ago> but it's gathered a lot of cruft over the years In what way? The Common Lisp standard hasn't changed since 1994. > essential features like multithreading are not standardized No one has made up their minds what the best atomic test-and-set operations are. A lot of platforms can't even agree on semaphores vs. condition variables. Which concurrency primitives do you think should be standardized, and which should be left to libraries? To me that seems like a trick question, because there's no good answer. For example, I think software transactional memory is a dead-end, and shouldn't be part of a language standard, but many people involved in Clojure obviously disagree. > More importantly, it doesn't have a focus on immutability and functional programming by default. You can always do FP in Common Lisp, but you can't do gotos in Clojure.
- tikhonj 14y agoClojure is nice, but the idea that it is somehow built for the real world where Haskell isn't is just patent nonsense that I wish people wouldn't repeat. You do not need to understand complex math to actually use Haskell! All the important ideas can be understood and used in Haskell terms alone--you can think of them just like the ideas and jargon introduced in other languages. Except more general, more elegant and more consistent because they have a unifying underlying theory which the people who designed them in the first place do understand. The biggest conceptual shift is to thinking functionally rather than imperatively, so it's going to be similar in both languages. The difference is that Haskell is more thorough, but the fundamental ideas are very similar. Haskell, of course, has many of its own advantages which are mostly detailed elsewhere. I'm merely going to give you my highest-level take-away from trying Clojure: Haskell has much better facilities for abstraction. Haskell allows you to use types and data representation specific to your donation while still allowing you to take advantage of some very generic libraries. And the custom types are not actually complex, unlike what Clojure leads you to believe with its preference to using the basic built-in types: you construct your types from basically three fundamental operations: combining multiple values into one (like a tuple or struct), giving a choice of values (like a variant or disjoint/tagged union) or creating functions. That's all there is to them! Basically, don't be afraid of Haskell, whatever the common wisdom is. As usual with these sorts of things, it's much more common than wise.
- rayiner 14y ago> Clojure is nice, but the idea that it is somehow built for the real world where Haskell isn't is just patent nonsense that I wish people wouldn't repeat. You do not need to understand complex math to actually use Haskell! In the abstract, possibly, but not in practice. You can't ignore the effect the general bent of the community has on the language and the code that is idiomatic in the language. People tend to describe Haskell code in mathematical terms, and libraries use operator overloading and the like in mathematical analogies.
- tikhonj 14y agoAll of the terminology used widely in the community can be--and almost always is--defined in terms of Haskell rather than math. You can pretend the math does not exist and treat it as language-specific jargon. You might miss out on the truly cutting-edge libraries until somebody writes a nice tutorial for them, but that would still be true even if the abstractions were not mathematical in nature. Many of the people in the community do not know much of the math beyond the terminology they learned in Haskell. That's certainly what I gathered talking to people at a local Haskell meetup and it matches my impression of many of the people online (e.g. in the mailing list or StackOverflow.
- jboggan 14y agoWe use a lot of Clojure here at Factual: http://www.factual.com/jobs/clojure http://www.factual.com/jobs/clojure I'm still in the process of learning from the Clojure gurus around here but I see that it has a lot to recommend it. I can already see increases in the clarity of my code when I write filters and functions for our data pipeline. The next step is to learn Cascalog. We're fielding a sizable contingent to the Clojure West conference this weekend (which we're also sponsoring) so come say hi if you're in out in Portland!
- bascule 14y agoI also started with Ruby (well, after a number of other languages) and used Clojure for a time, and I just can't sympathize with this: "And—if you like avoiding unnecessary frustration and boilerplate—it will make you happy." Didn't get this feeling. I like avoiding unnecessary frustration and boilerplate! A great way to avoid boilerplate is to hide it behind macros, however that's not necessarily a great way to avoid frustration. Know what's really awesome? When a macro injects a recur point, and suddenly you're not recuring to where you think you are, you're recuring to a point within the macro somewhere. The only way to figure this out is to go dig through the source of the macro. Sorry Clojure fans, what can I say? This did not make me happy. I am told that if Clojure did not make me happy, that's my fault, because I didn't study Clojure hard enough or something to get to the point where I should feel the Zen of Lisp flowing through my brain. Clearly this must be the blub paradox at work. Maybe it's my fault, or maybe Clojure isn't the greatest language in the world for everyone.
- tensor 14y agoThere is no language that is "the greatest language in the world for everyone." It's unfortunate that you found a point of frustration with clojure (or with one of it's 3rd party libraries?), though a single anecdote about a single problem you encountered shouldn't turn you or anyone else off a language. As for macros, they should be used with care for many reasons, this being a good example. Similarly for ruby, monkey patching should be use with great care as it can introduce more problems than a surprise recur point.
- weavejester 14y agoMacros have a great deal of power, which is why they should almost never be used. A macro injecting a recur point sounds just a little bit insane. I can't think of a reason why you'd ever do that.
- kreek 14y agoAny recommendations for a web framework in clojure? I played around with Noir for a while but it seems like that project is abandoned now? What's the Sinatra/Flash of Clojure?
- DigitalJack 14y agoCompojure, Ring, and Enlive or Hiccup are a pretty common stack.
- adambard 14y agoIt should be noted that Clojurers are very much about having composable libraries with narrow applicability. In Sinatra or Flask, you get a server (interface), a routing syntax, and built-in templating. In Clojure, you have Compojure, which handles routing, Ring, a server abstraction for requests, and responses, and the templating library of your choice. (I've used Hiccup and Enlive, as well as Mustache and Markdown). You're responsible for gluing them together, which is really not too hard given the power of the language to create abstractions on the fly. This results in slightly more code, but also makes it much easier to replace or augment any one component.
- weavejester 14y agoTo be fair to Sinatra, it uses Rack underneath, and farms out templating to different libraries. It's certainly more of a framework than Compojure is, but it's not monolithic by any means.
- swah 14y agoIn one particualr website, it was much simpler when I removed Compojure. I remember thinking that was pretty cool. (Seeing clearly what Compojure did and dropping it in favor of a simple hashtable).
- tensor 14y agoThis is currently one of the best sites explaining the clojure web stack: http://www.luminusweb.net/ http://www.luminusweb.net/ There isn't really a single framework, rather you can pick and choose your components depending on your needs or preferences.
- gtani 14y agoThis guy reminds me of Uncle Bob
- robertfw 14y agoCan anyone speak to the experience of debugging Clojure, especially without having JVM experience? The one thing that has me concerned is the depth of crash dumps and the amount of JVM knowledge required to interpret them.
- tensor 14y agoOthers experiences may vary, but mine look something like this. First, there is a stacktrace library that you need to use if you get runtime errors. This stack trace gives you line numbers and function names, so it's pretty easy to track the problem to the nearest named function. From there, and for other errors, generally I use print debugging. Often times you can also just test a function in isolation on the REPL. This and the fact that you can hot-load code into a running process make print debugging tolerable. There are fancier debugging tools in development for clojure, though I have no experience with them. Essentially they let you attach a REPL at arbitrary failure points. This would make it quite easy to identify the source of the problem. Knowledge of the JVM does come up, but you won't be digging through compiled bytecode or the guts of java libraries (unless you use a lot of java library interop).
- osbertlancaster 14y agoHow does this compare to lisp, where you can break straight into editing code, inspecting variables, etc, and then continue? This seems to be something Clojure really lacks, but I never see it explicitly stated in 'why you should use Clojure' articles, nor in Clojure books. What I want to read is a sober 'pros and cons of using Clojure' article, so I can properly judge whether I should switch.
- _casperc 14y agoWell the stacktraces are deeper, there is no way getting around that. In practice it's not much of a problem though as you quickly learn to identify the lines from your own code. Debugging tends to be more REPL based than debugger based. It is possible to debug from Eclipse using the build in debugger, but it's not something i have done as it is not really necessary.
- berlinbrown 14y agoClojure has been grown up, it hasn't change that much since several years ago, especially on the surface.
- alexatkeplar 14y agoI wrote an event collector for SnowPlow in Clojure (https://github.com/snowplow/snowplow/tree/master/2-collectors/clojure-collector https://github.com/snowplow/snowplow/tree/master/2-collector...), and really enjoyed the experience. Leiningen is excellent, far better than any other build tool I've used, and Ring and Compojure were both great. My only grumble with Clojure is that nobody seems to document the types that their functions take and return. It's a PITA having to read through a whole chain of functions just to figure out the types which are passing through it.
- caycep 14y agoI'd like to play around with this (as well as actually read SICP). However, does the fact that Apple keep blacklisting the Oracle JVM get in the way? Would be nice to have Clojure bundle its own JVM rather than have a dependency, unless I am totally doing something wrong in setting it up (homebrew).
- xaritas 14y agoI use Java daily on my Mac, and it has never been a problem. I don't remember doing anything special to defeat any blacklisting, either. I believe that Apple's anti-malware agent is simply disabling the Java browser plugin. Regardless, it doesn't seem to affect desktop development, so Clojure on!
- Freaky 14y agoWeird font rendering on this site - the glyphs are very distractingly blobby. Increasing or decreasing the zoom level helps a lot if anyone's finding it similarly unreadable.
- MrMan 14y agothere is a gulf between clever and smart. it may be clever to use Haskell, but is not smart to hijack a clojure thread to argue about it, again. if I had the power to downvote I would be using it here.
- razielek 14y agoAnybody would recommend Eclipse instead of Emacs? Or maybe other IDE? I don't want to learn Emacs and its keybindings, but if I have to, better tell me now. :)
- secoif 14y agojust learn emacs or vim. it's for the best.
- wging 14y agoLight Table is still in beta, but it is looking very promising.
- Rayne 14y agoMost people are going to prefer Emacs, but lots of people happily use Eclipse. Light Table is also a budding option. Vim is also fine if you're into that. ST2 can suffice with the https://github.com/odyssomay/sublime-lispindent https://github.com/odyssomay/sublime-lispindent plugin.
- bitwize 14y agoIf you work in a Lisp dialect, the time you invest upfront in learning Emacs keybindings will pay off massively later. besides which eclipse is a finicky monstrosity like visual studio
- keyle 14y agoOh my, the flame wars. Search for instances of the word "haskell" and "clojure" to see what I mean.
- virtualwhys 14y agoLuminus and LightTable (wow, that in-editor javascript demo) look pretty awesome. Coming from Scala/Play my initial resistance to jumping the fence are: 1) lack of compile time type safety 2) odd, for me, language syntax 3) no ScalaQuery/Slick functional SQL wrapper equivalent How is Scala-Clojure interop? Would be interesting to jar up existing Slick-based model layer and invoke within Clojure stack ;-) Not having yet taken the plunge, based on the LightTable demo Clojure development seems pretty rapid fire (read: no waiting for compiler to catch up).
- brehaut 14y agooptional clojure type checking: https://github.com/clojure/core.typed/ https://github.com/clojure/core.typed/ (not finished, but showing promise)
- olenhad 14y agoFor sql wrappers do checkout Chris Granger's korma (sqlkorma.com/docs), clojureQL(https://github.com/LauJensen/clojureql https://github.com/LauJensen/clojureql), hyperion (https://github.com/8thlight/hyperion https://github.com/8thlight/hyperion) etc.
- virtualwhys 14y agoI did run through Korma docs; if I were coming from Rails or other ActiveRecord based framework I might get excited, but as soon as I see start to see things like has-one and belongs-to I get worried about the generated SQL. ClojureQL, however, looks intriguing, seems more functional than the alternatives listed here. Would love a more rapid fire development experience than what Scala/Play offers, but for now there's a price to pay for type safety. Clojure seems a great call for the dynamic side of the fence, and being on the JVM with its massive ecosystem is a major plus.
- HNLogInShit 14y agoWith the falling popularity of Java, is there a risk that VMs will not be maintained? They're already omitted on some platforms (Mac OS).
- dogweather 14y agoThis is a very intriguiging post it constantly makes reference to Rails and Django. But it stops there at the abstract. Can someone point to an A/B comparison ... a simple Rails/Django app and the Clojure equivalent? "Just show me the code."
- juskrey 14y agoAs for me, I did not even know the word "homoiconic", until yesterday, when I bought a book on Clojure, after reading the author. What I do know, is that I was in love with Assembler since my first steps in programming and hacking. While everyone in my surroundings were using pascal and basic that days, inlining asm only for occasional IO work, I used to scaffold tremendous routines and structures in a matter of days, using base asm and macro. While my friends, looking at my sources, were only able to say "what the ...ck is this, that is insanly sick, how do you understand all this?", asm was so natural and fluent to me. Then dark times of C and C++, Java, C# etc. followed (BTW, I hate purified OOP deep inside, it always seemed to me so unhuman), and several years ago my roads crossed with LUA, and I instantly loved it. Pity, I had no chances to use it much, but I remember that feeling, when code and data magically interlace and create beautiful structures. Now I am looking at Clojure and recalling my Asm youth, and these awesome days with LUA. But this time it has all the power of interop with major libs and services. I am giving it a try.
- bitwize 14y agoNo thanks, I'll stick to Gambit. Fast, RnRS/IEEE Scheme compliant, has a great runtime layer and FFI, can integrate with anything written in C.