19 ms·
Why Clojure? (2010)
- gigatexal 10y agoThere should be a rule that if one writes a post saying language X is faster than languages A,B,C there should be some real world benchmark to add data to the discussion.
- pjmlp 10y agoWhich are mostly worthless, because most keep mixing implementations with languages.
- paveway 10y agoAnd benchmarks with rigor, I might add. Noting important dependencies that match chipset, bare metal CPU architecture/bus wiring and compiler choices. In particular, I've spoken with people who have cited significant differences in performance, when using proprietary compilers matched to vendor CPU chipsets, for Linux/OpenJDK compilation, which then changes the profiling of the JVM benchmark, on the same bare metal crate. Meanwhile, L2 cache misses, due to object reference churn, are the final deal breaker with the JVM, if I've read correctly and read enough about JVM performance. Beyond even garbage collection overhead, fundamental JVM performance cannot be tuned to optimize CPU cache use. Briefly paraphrased, the JVM performs messaging/referencing with String references, that look like "java.lang.Object@%HASH_CODE%" and when you instantiate and garbage collect many instances (millions of those hellishly long fully qualified java names) across many operations, costing many cycles, you'll always suffer incurred latency, because most of your objects are frequently populated and then evicted from the L2 cache, no matter how long they actually live in the JVM heap. I don't have the link handy, or I'd post it. But long story short, even though a JVM benchmark may be performant, benchmarks do not peg CPU resources according to real life use cases. And changing the OS, motherboard, and compiling from source on your own physical hardware can provide benefits that might not be obviously worth the extra effort to compile from source bootstrapping all the way from the kernel to the JVM, before deploying your java artifacts.
- WillPostForFood 10y agoThat a fair request, but the article doesn't say Clojure is faster than any other language, it just says it is fast. That caught my attention as well, because I don't think of it as being particularly fast (mostly due to startup time).
- throwaway7645 10y agoProbably being compared to languages like Python, Ruby, and Perl. It should be pretty close to statically typed languages on the JVM like Scala. I think a real REPL is worth a little bit of performance.
- RyanHamilton 10y agoFYI http://jpad.io/ http://jpad.io/ REPL for java
- sgift 10y ago> because I don't think of it as being particularly fast (mostly due to startup time). Proposal: Fast for server use-cases? Curiously, I was never really interested in the startup time of most of my code, probably because most of my code is long running where it doesn't matter if it takes a few seconds more to start.
- fnordsensei 10y agoThere are a few efforts out there to provide something with near instant start up time. Can be useful for scripting, for example. Planck, which runs on JavaScriptCore: http://planck-repl.org/ http://planck-repl.org/ Lumo, which runs on V8: https://github.com/anmonteiro/lumo https://github.com/anmonteiro/lumo
- edem 10y agoI was not interested in that either until I had to start Java processes by hand. The initial version ran for 5 minutes. I then refactored the app to be a long running service instead of a fire-and-forget app and the run time changed from 300 seconds to 300 microseconds!
- wahern 10y agoThey left out the part where Clojure DOES NOT implement tail-call optimization for mutually recursive functions. Without TCO, you can't fully leverage functional composition and immutable data structures without introducing some ugly hacks or relying on other language-level constructs offered by the implementation--that they can't be implemented in the language strongly suggests something about the limitations of the language.[1] A great language that does optimize mutually recursive tail-calls, among many other elegant features: Lua! ... TCO, asymmetric stackful coroutines (90% as powerful as call/cc, but with zero calories), lexical closures, prototype-based object orientation, duck typing-based object orientation (among other possibilities), and a first-class C API that allows C code to work cleanly with coroutines, closures, the object system(s).... Lua is truly multi-paradigm. The only downside is dynamic typing, though that's not always a liability and often an asset. Also, Lua has other interesting features, like lexical global namespace substitution using _ENV, that permit devising solutions to minimize some of the headaches of dynamic typing. And because Lua is so powerful in so many dimensions, yet so simple and tiny, writing unit and regression tests is often a breeze. Once you add the canonical extension module LPeg into the mix (written by one of the Lua co-maintainers), Lua is about as formidable as they come. Only Perl 6 comes close to the ease of writing parsers with Lua+LPeg. [1] The JVM will eventually add support for implementing TCO in Clojure and other languages, at which point many Clojure proponents will find religion in the power of TCO.
- brandonbloom 10y ago> Without TCO, you can't fully leverage functional composition and immutable data structures Look, I like tail calls as much as any language geek, but this statement is just plain silly. The idea that TCO is needed to "fully" leverage anything is silly. Never mind that necessitating so-called full leverage is pointless, as even supposedly partially leveraged anything can be useful. In the case of Clojure, function composition and immutable data structures are highly leveraged and, after learning the seq abstraction and lib functions, you won't even miss tail calls unless you try to write a direct-style interpreter for a language that supports recursion.
- willtim 10y ago
- grzm 10y agoFull title: Why Clojure is better than C, Python,Ruby and java and why should you care I recommend updating the title to "Why Clojure is better than C, Python, Ruby, and Java"
- edem 10y agoThat was the original title but someone changed it. A mod maybe?
- Nekorosu 10y agoThe original title is more of a clickbait. The article highlights good things about Clojure but it doesn't tell anything about the languages mentioned in the title. The current one is much better.
- grzm 10y agoIt also agrees with what the original post was entitled.
- armitron 10y agoOne issue with Clojure is that it comes with strong opinions (STM, immutable data structures, JVM-Java ecosystem) and thus is not as paradigm-enclosing as other Lisps (e.g. Common Lisp). I'd much rather have SBCL's native code compiler, read/compiler macros, conditions and restarts (that I end up using on pretty much every project) and optionally use libraries for immutability and STM (if and when I need them), than compromise from the get-go and use a language that reduces the set of available options by forcing its specific worldview. If I do need a strong focus on concurrency, I find Erlang (and also Elixir) a much more coherent solution. The cognitive dissonance that comes from having to interact with Java when using Clojure is very damaging and it can't be abstracted away. Just look at Clojure stack traces. So to end with, Clojure proponents should understand its limitations and design choices. It was created because Hickey needed a language to solve problems he was having in his specific arena (delivering concurrent applications in the Java ecosystem with his consultancy) and not really to improve on the Lisp state-of-the-art side of things. If you're a Java guy and absolutely need to stay in that ecosystem, I guess you can go with it. Otherwise, you end up giving away too many things. This has been validated in practice, in the Common Lisp community. We get a lot of guys who are coming _from_ Clojure, but it is rare for someone to move _to_ Clojure from CL.
- spraak 10y ago> The cognitive dissonance that comes from having to interact with Java when using Clojure is very damaging and it can't be abstracted away. Just look at Clojure stack traces. This is what has kept me from really feeling comfortable getting into Clojure. Unfortunately there are so many downsides in the Functional programming world :( It's either: 1. Have a strange interrop (Clojure with Java, and even though Elixir with Erlang isn't as bad, it still bothers me) 2. Lack of mainstream adoption (e.g. Haskell, yes FB uses it for their spam filters.. but mostly working developers predominantly use other languages) 3. Lack of clear tooling choices or implementations (Haskell's stack vs. platform, or Scheme is great but no one popular implementation) (I know I'm being quite pessimistic)
- agumonkey 10y agoWhat's so weird about clojure interop ? I rarely find myself going back to write full java code when in a repl.
- hotBacteria 10y agoJust to add a bit of context, this article was written more than six years ago: http://thecleancoder.blogspot.fr/2010/08/why-clojure.html http://thecleancoder.blogspot.fr/2010/08/why-clojure.html
- grzm 10y agoThanks! I knew I had read a blog post with this title somewhere, but I couldn't put my finger on it. Here's the related HN post from 6 years ago: https://news.ycombinator.com/item?id=1615182 https://news.ycombinator.com/item?id=1615182
- haylem 10y agoSame here: I was reading and when I read the anecdote about a some basic concept being introduced only around page 216, I thought "hang on, I've read that before..." And I had the same thought as back then, too: "Concepts, Techniques and Models of Computer Programming" also used this approach, except it's only after a few chapters that they teach you "oh by the way, Oz also supports for and while loops" whereas everything until now used recursion. All my eng school buddies found that off-putting, but I always thought that if you put the book in the hands of a completely newcomer to programmer, they would never even think of it. (I know SICP predates CTM by decades and may not be considered in the same league, and that Mozart/Oz is rather more obscure that any lisp/scheme ever can be, but I consider it a fairly important book as well, and one of the best textbooks I've ever read: very well structured, well written, very complete, starts shallow but goes very deep and very wiiiiidddeee in terms of knowledge.)
- deleted 10y ago[deleted]
- dang 10y agoThanks, we changed the url to that from http://telegra.ph/Why-Clojure-is-better-than-C-PythonRuby-and-java-and-why-should-you-care-12-20 http://telegra.ph/Why-Clojure-is-better-than-C-PythonRuby-an.... It's annoying that the latter article put a false date on the piece.
- jakebasile 10y agoBit of an aside, but this is the first I've seen an article published on telegra.ph, Telegram's Medium-like article hosting service. See: https://telegram.org/blog/instant-view https://telegram.org/blog/instant-view
- reitanqild 10y agoSame here, first time I have seen one "in the wild". Extra nice since I first saw the article in the chat with the HN bot on Telegram.
- 4lejandrito 10y agohttps://news.ycombinator.com/from?site=telegra.ph https://news.ycombinator.com/from?site=telegra.ph
- rooundio 10y agoMy "functional programming epiphany" came in a talk by Martin Odersky, who remarked that imperative programming is like thinking in terms of time, whereas functional programming is like thinking in terms of space. Don't think about the sequence of how to achieve things, but the building blocks needed to do so. That nailed it and made me a Scala convert ever since.
- junke 10y agoWhy not think both in terms of space and time?
- zdkl 10y agoClojure core.async!
- anewhnaccount 10y agoLike this? http://db.cs.berkeley.edu/papers/datalog2011-dedalus.pdf http://db.cs.berkeley.edu/papers/datalog2011-dedalus.pdf
- kazagistar 10y agoI mean, thats what imperative programming ends up being to some extent. But the idea is that the less things you can think about, the better.
- throwaway7645 10y agoBest example I heard was in an F# talk. The guy used a bar tending analogy: FP => I'll have a Sazerac Imperative => Excuse me sir, could you take some ice, add rye whiskey, add bitters, add absinthe, shake, strain into a glass, and add a lemon garnish before bringing it to me
- owyn 10y agoFP is more like: drink(sazerac(garnish(strain(shake(absinthe(bitters(whiskey(ice(glass))))))))) Ultimately it's the same result? The difference is when you can reuse and compose functions.
- fleetfox 10y agoI got book about clojure and was really trying to get into it. Some of the concepts really resonated with me but i can't get over the lisp syntax.
- junke 10y agoWhat is so annoying with the syntax? I honestly don't get it.
- kimi 10y agoI also hated the syntax when I got started. I found it very hard to read Clojure code. After a while you use it, you will not "see" it anymore (and instead you will appreciate its clarity). Don't give up!
- Slackwise 10y agoIt also helps to turn parens grey via syntax highlighting so they are still visible, but don't clutter all the wonderfully wordy symbols. I've also started turning all the special character noise down in all languages now. I'm usually trying to read the words, not all the cruft.
- nodivbyzero 10y agoIs Clojure better than Erlang?
- sgift 10y agoDepends on your definition of better. It runs on the JVM, so you have easy access to the whole ecosystem of libraries. For me, that's always a big plus compared to non-JVM languages, but if you don't use that the case gets less clear.
- mping 10y agoStarted doing some erlang work, I'm very impressed in the overall design of the thing. I'd say erlang is very well suited for heavy,low-latency networking because of the design of the VM and the characteristics of the language, whereas clojure is a bit up the stack. Anyway if you prefere parenthesis you got Lisp flavoured erlang: http://lfe.io http://lfe.io
- pron 10y agoThe problem with Erlang is that it's veeeery slow, so you'll need to write the computation-heavy stuff in C.
- networked 10y agoI am new to Erlang. I assume that you mean writing a linked-in driver or NIFs. Unless you need very low and precisely controlled latency for your computation-heavy code, too, why not write it, e.g., in Python with NumPy and talk to the Python process over a port?
- pron 10y agoYou could. Or you could just run on the JVM. Either way, there are some tradeoffs to make.
- 10y ago
- alkonaut 10y agoSo, why not clojure? (Warning: subjective, and a bit toungue in cheek): - Clojure is a Lisp. Lisps are very elegant in their simple tree syntax, so compilers like them, and reasoning about Lisp code is a joy. However no one has yet figured out how to represent Lisp code in good a way that doesn't require a large number of parentheses, often stacked together in groups of three or four. If you have a slight astigmatism this (((()) will not help. - It's a jvm language. That has gives all the benefits you want in a functional language such as type erasure meaning you can't make a data structure of primitive types without either pretending they are objects (boxing) or writing a custom type. Also, you have access to the vast amount of jvm libraries, almost all of which use mutable data structures and nulls everywhere. Jvm lacking proper tail calls will also give you the joy of having to manually specify when you want tail recursion rather than just recursion...from the tail.
- junke 10y ago> compilers like them Editors too.
- sandbags 10y agoAlthough macros can make life difficult for clever editors that want to introspect code.
- yogthos 10y agoThis is mitigated by the fact that Clojure doesn't expose reader macros to the user.
- adrianm 10y agoDon't macros actually help both compiler writers and end users here? Macros are expanded at macro-expansion time, which is a stage before code gets evaluated. Macro-expansion is akin to source code pre-processing in other languages. Therefore all necessary context for fully expanding a macro in Lisp is maximally a source file and minimally a single macro form within some shared compilation environment. Clever editors (like Emacs extensions commonly used by Scheme, Common Lisp, and Clojure programmers) make ample use of this functionality to provide all sorts of code introspection and other smart editing functionality.
- bschwindHN 10y agoBeing able to target servers, web applications, and mobile apps is compelling enough for me (at least for personal projects). Throw in the simplicity of the syntax and the low dev iteration times and it makes me have to ask "Why not Clojure?" when starting something new.
- rubber_duck 10y ago>and mobile apps Last time I tried (which was probably over 2 years ago by now) the CLJ android had a huge loading time to the point of not being usable for anything serious (it offered no tangible benefits that would justify the load time it had) and iOS was something based on that JVM for Android port that Xamarin bought then shut down. Has that changed ? Or are you talking about CLJS + ReactNative and similar tech ?
- bschwindHN 10y agoYeah I'm talking about react native. I'm on mobile at the moment but look up "re-natal", it's built on top of react native with re-frame, it's superb. Edit: https://github.com/Day8/re-frame https://github.com/Day8/re-frame https://github.com/drapanjanas/re-natal https://github.com/drapanjanas/re-natal
- preek 10y agoI had a BA student write his thesis on this matter. What if I want to write a system that has a web app, api, iOS and Android app? How can we mitigate the gazillion different languages and paradigms? Turns out, it's easy with Clojure. Have even written desktop apps with it since.
- bschwindHN 10y agoIs that thesis publicly available? I'd love to read it.
- vesak 10y agoI think my language of focus in 2017 will be Racket. It seems to be the perfect combination of optional (but somewhat static!) strong typing, highly advanced features and cool Lispness without becoming impractical. Minilanguages... for everybody!
- throwaway7645 10y agoI have a comment on Racket below. I like the concept, but it seems to be pretty slow. I'm also not sure how many mini-languages are out there. What the "Red" language team is doing seems to be a similar concept. That makes sense as Racket is a Lisp and Red is mostly from Rebol, but has a native code compiler and comes with a tiny .exe. Their GUI engine is phenomenal.
- capnrefsmmat 10y agoOn Scheme benchmarks, Racket does fairly competitively, probably due to its JIT: http://ecraven.github.io/r7rs-benchmarks/benchmark.html http://ecraven.github.io/r7rs-benchmarks/benchmark.html (Chez is still freakishly fast.) However, if you're writing code in DrRacket, it has full debugging information enabled, which may slow the code down. So your REPL performance in DrRacket may be slower than if you ran Racket from the command line. https://docs.racket-lang.org/guide/performance.html https://docs.racket-lang.org/guide/performance.html
- royallthefourth 10y agoThe debugging slows the code down a ton in my experience, and it also prevents futures from running in parallel. Trying out the futures code from the guide, failing to disable debugging slows down the final Mandelbrot example by something like 100x on my machine. Fortunately, DrRacket's friendly GUI makes it pretty easy to toggle debugging. I leave it in place most of the time, but occasionally the slowdown is just unbearable.
- throwaway7645 10y agoThanks for the tips! I'd like to use ChezScheme, but haven't found a good way to get into it.
- twoquestions 10y agoI tried and really wanted to like Clojure, but I hated the error messages. I love how it's a lisp, I love how you write programs in it, I love the REPL, it all just feels nice to me.... until I miskey something or make some other error. Then the compiler seems to hate me personally. "Here's a haystack where the error /might/ be, have fun finding the needle dipshit." Maybe I'm just spoiled with Elm, Rust, and Elixir's error messages, but the last time I tried Clojure (more than a year ago) I just hit a wall when I tried to make a toy app, as the Clojure compiler seems to hate me even more than C's compiler does. Has this situation improved? If so, I'd love to take another stab at it.
- jeremiep 10y agoI always use something like clj-stacktrace[1] to pretty print error messages and I've never had any issues figuring out what the problem was. Most of the time you're working from the REPL inside your editor anyways so the iteration loop is much, much better than any other language's. Even without clj-stacktrace I'd still prefer Clojure development to anything else. Rebooting a program and losing state is always worse than error messages taking a bit longer to understand at first. [1]: https://github.com/mmcgrana/clj-stacktrace https://github.com/mmcgrana/clj-stacktrace
- jgalt212 10y agothis seems a jillion times better than a standard stacktrace. why isn't it in built into the core?
- jeremiep 10y agoThe core just uses whatever the VM under it has for error handling. Clojure is a hosted language and one of the best decisions it made was not to hide the VM its sitting on (either the JVM, CLR or JS - all have slightly different exception handling). I see it more as a development library and don't ship it to production. There's also cljs-devtools and dirac to enhance the chrome devtools with ClojureScript support. Once you try them you're not going back :)
- dominotw 10y agoWe had a majority of codebase in clojure back in 2011, but we found that that presented us with major roadblocks hiring new team members. Even some experienced people had hard time getting into and learning curve was non-trivial. So we dropped it. Prbly not a good idea to build a big company with not so popular prog language [1]. 1. http://www.tiobe.com/tiobe-index/ http://www.tiobe.com/tiobe-index/
- yogthos 10y agoMy team has been using Clojure for the past 6 years, and we have the opposite experience. Most new developers we've hired haven't used Clojure before, but they were able to become productive doing useful work within weeks. The fact that we're using Clojure tends to be a positive factor for attracting candidates as well. A number of candidates we've interviewed mentioned that Clojure was the reason they applied for the job. They heard about the language and they were interested in trying to work with it professionally. In addition, we hired contractors and co-op students to work with our team, and they were able to pickup Clojure as well. At this point I would actually use Clojure as a filter. I'm rather suspicious of any developer who wouldn't be able to learn Clojure.
- felideon 10y agoWhere are you located? It's hard to find people (a) willing to make the jump and (b) making the jump effectively. And when you do, you can maybe tap into x number of devs for your team, but trying grow to 2x devs is much harder.
- yogthos 10y agoI'm located in Canada, and work at a research hospital in Toronto. We have a number of companies using Clojure in town, and run a meetup. As part of the meetup we're also running a Clojure workshop, so that helps a lot. I also found that hiring students for junior positions from university works great as well. They don't have preconceptions about how to do development, and usually have easier time picking up new paradigms than devs who've been working in a particular one for a long time.
- MarcusBrutus 10y agoI've used Clojure in a few cases and I totally adore the simplicity of its Lisp syntax as opposed to the baroquesque abomination that is Scala. However, lack of strong typing is sorely felt. I 've done a little playground-style OCaml coding and the feeling you get with OCaml is that once your program compiles, it most likely also runs correctly. Is a Lisp language with strong typing for the Java ecosystem too much to ask? Apparently it is or else we would have had it by now.
- jeremiep 10y agoTheres the new clojure.spec[1] in 1.9 and core.typed[2] adds an optional type system as well. [1]: http://clojure.org/about/spec http://clojure.org/about/spec [1]: https://github.com/clojure/core.typed https://github.com/clojure/core.typed The REPL-driven development of Lisps makes types not as important because everything is interactively tested as you write it. Having an optional type system makes it much easier to start with dynamic types and gradually add type annotations as your architecture stabilizes.
- yogthos 10y agoConversely, lack of mutability makes dynamic typing much easier to reason about. Since variables typically can't be changed via side effects, you can do local reasoning about your code vast majority of the time.
- rkrzr 10y ago> Conversely, lack of mutability makes dynamic typing much easier to reason about. Dynamic typing does not imply lack of mutability. Those are unrelated concepts. Python and Ruby are dynamically typed but both are certainly mutable. Conversely static typing actually makes it easier to reason (locally or not) about things, since you always know the type of everything.
- jeremiep 10y agoI think he meant it in the context of Clojure, which has immutable values. I don't feel static typing makes it easier to reason about, at all. Reasoning about values and their transformations is more important to me than reasoning about types, and since values carry types you're actually working with more information. Most of the time the types I'm interested in are closer to concepts (sequences, mappings) than concrete classes. Thats where having immutable dynamically typed values is better than having statically typed mutable ones.
- deleted 10y ago[deleted]
- sandGorgon 10y agoThe jvm platform has become (again) the most exciting platform to work with in recent times. And my favorite there is Kotlin. kotlin 1.1 (still in milestone) is a brilliant and compelling language to use on the JVM. Spring 5 is a very "functional" web framework that will come out in a few months with first class kotlin support (even today, it is fairly excellent [1]) Vert.x [2] has incredible support for Kotlin and is coming up with built in kotlin support. Coroutines got merged fairly recently [3] Reactor (https://projectreactor.io/ https://projectreactor.io/) and Rxjava have had kotlin support for a long time. The tooling is excellent (umm.. it was developed by Jetbrains). The killer app/functionality ? Android. Kotlin is the swift of Android and that's where its uptake is coming from. [1] https://github.com/sdeleuze/spring-boot-kotlin-demo/tree/all-open https://github.com/sdeleuze/spring-boot-kotlin-demo/tree/all... [2] http://vertx.io/whos_using/ http://vertx.io/whos_using/ [3] https://blog.jetbrains.com/kotlin/2016/07/first-glimpse-of-kotlin-1-1-coroutines-type-aliases-and-more/ https://blog.jetbrains.com/kotlin/2016/07/first-glimpse-of-k....
- donjigweed 10y agoFor me, Clojure is the most satisfying language to write in. The design of the language feels impeccable most of the time. Working in the repl, with all of your application code loaded into the runtime, sitting in an adjacent terminal or editor tab, is immensely satisfying, much like the experience of a craftsman working with hand tools. Unfortunately, I find Clojure code to suffer in terms of readability, and I think it suffers from the same problem all dynamic languages suffer from, they just don't scale to larger applications and teams as well as static languages do. Proof of this is the fact that pretty much every dynamic language out there eventually looks to graft something like a static type system on after the fact. Basically I think people advocating Clojure outside the context of small, high ability teams are (mistakenly imho) prioritizing write mode over read mode.
- iLemming 10y agoau contraire - many find Clojure code extremely readable (even compared to other Lisps). It's possible to write some obscure functions in any language, developing good taste and habits to write nice and reasonable code is just a matter of practice. I believe Clojure gives you enough discipline to learn that fast. It just seems there are certain types of devs who are inherently dyslexic - they struggle to read Lisps. Where a Lisp developer sees structure and beauty they see nothing but quivering beehive of parentheses.
- vonnik 10y agoFwiw, here's a deep learning framework for the JVM that some Clojure people are using: https://deeplearning4j.org/ https://deeplearning4j.org/ I bring it up not just because LISP was conceived as a language for AI, but because of the points about distributed computing made in the post. Multithreading is baked into the JVM, which is important because advances in AI are computationally intensive.
- aliakhtar 10y agoIn what ways is Lisp / Clojure better for AI than say, Scala?