15 ms·
How innovative is Clojure as a Lisp dialect from Lisp expert's perspective?
- lbj 8y agoThere are alot of interesting points of view in that thread, unfortunately they're all from people who've spent very little time with Clojure. The biggest innovation I think, its putting Clojure on the JVM allowing for tight host integrations. This has been my way of introducing Clojure in a number of places it wouldn't otherwise have been able to go. In terms of writing better code, the performant immutable datastructures yield more power than I can sum up a single comment.
- jlarocco 8y agoIt's debatable how innovative that was because ABCL was running on the JVM before Clojure. Clojure was definitely marketed better, though.
- mark_l_watson 8y ago+1 for mentioning Armed Bear Common Lisp. I usually use SBCL but ABCL is great when you need Java interop (I use it with DL4J). I have used Clojure when requested by customers (about 18 months total) since its inception: I donated to Rich when he asked for community support because I liked the Common Lisp to Java bridge he wrote many years ago. Clojure is a good language that has a uniform API for anything that is a sequence and I (usually) like working with immutable data. That said, I enjoy CL and Scheme more.
- agumonkey 8y agoNot marketing, just a bunch of different core ideas, immutable/concurrent first. It was a lot more attractive than yet another CL port.
- jfoutz 8y agoThe jvm is really nice. Operationaly, it’s kind of a pain. You can upgrade the installation on bare metal, you can play the packer game and ship new vms, or you can have crazy fat docker containers. K8s can sort of deal with the vm model, but it’s beta. Go is pretty nice in this regard. I should look into racket and chicken again for static binaries. I gotta say “from scratch “ is a fun way to start a dockerfile
- slondr 8y agoIf you want to write a program in a Lisp and ship it as a compiled binary, your best bet is to use Common Lisp and compile it with SBCL. A stripped SLAD binary will be way smaller with way less overhead then running a whole host of bytecode on a VM like Racket or Clojure.
- drcode 8y agoBut few people care about overhead or executable size much anymore, outside of embedded systems. What most people care about is computational performance, and clojure performs OK by this metric (certainly SBCL can still beat it in many use cases on this metric as well, but often only by a modest margin)
- fiddlerwoaroof 8y agosbcl also has the ability to statically link all your C dependencies using CFFI’s STATIC-IMAGE-OP
- lincpa 8y agoClojure can also do it. Java Abstracted Foreign Function Layer https://github.com/jnr/jnr-ffi https://github.com/jnr/jnr-ffi
- fiddlerwoaroof 8y agoI don't think that's exactly the same: CFFI has the ability to bind C libraries with minimal boilerplate just like jnr-ffi does. But, in addition, with CFFI (and sbcl built with a particular set of flags) you can generate an CL image that only depends on GLIBC because you've statically linked all your .so dependencies into the resulting image.
- varjag 8y agoThere's been a few Lisps targeting JVM since early 2000s, back when JVM arguably had a lot larger mindshare.
- pjmlp 8y agoGiven the amount of embedded devices with a JVM running on them, and the OSes that have someone selling a JVM for them, I would say the mindshare is even bigger nowadays, just not hip as it once was.
- varjag 8y agoUnless you count Dalvik, there's probably more embedded devices running Node than JVM nowadays. The share of Java related technology has definitely declined on most platforms.
- pjmlp 8y agoSIM Cards, eletricity meters, Cisco phones, Ricoh printers, factory control systems, IoT gateways, BluRay players, there are tons of invisile JVMs running on the wild.
- cmiles74 8y agoI found the conversation to be sub-par and disappointing. I also find it discouraging that these arguments inevitably boil down to a Clojure-vs-Common-Lisp argument. What about Racket, Guile, Chicken Scheme, etc.?
- deleted 8y ago[deleted]
- nightfly 8y agoProbably because CLojure feels the closest to Common Lisp, so it's the best comparison.
- chii 8y agoI wonder how good clojure is with soft real-time like graphics rendering/games, or as an embedded script engine.
- harlanji 8y agoI’ve embedded Nashorn in Clojure and the environment is able to be inspected with Java development tools at runtime. Objects are able to be put into the JS context, hypothetically with native linked libraries without hastle. JS is single threaded so there should be no issue if the native library is not thread safe, and Java makes single thread guarantees. IIRC one can tie the script runtime to a thread, and create several per process and put them in a scheduler like any other thread. Ie. probably as good as native.
- dustingetz 8y agoFor real-time graphics, i think there is an impedance mismatch with the GPU data structures which are basically big mutable array buffers
- agumonkey 8y agomaybe used as a dsl interface for gpu ... I don't know
- dustingetz 8y agoI think you want the same datastructures moving up and down all layers of stack, otherwise you pay a marshalling penalty at each layer which is terrible for perf. If this is true, then we'd need to see fast immutable memory models inside GPUs that could natively represent persistent trees (moving away from pointers to mutable array buffers). Otherwise, the imperative way will always be at least C times faster, which seems a dealbreaker for the trailblazing researchers who forge the path the application layer follows.
- markc 8y agoYes, for example https://neanderthal.uncomplicate.org/ https://neanderthal.uncomplicate.org/
- kccqzy 8y agoI think Clojure is certainly innovative in that it includes software transactional memory in its core language. Scheme doesn't, Common Lisp doesn't, and perhaps most other lisps do not. It's not very often used, but it's a welcome addition to the core language.
- bad_user 8y agoSTM has nondeterministic performance characteristics and doesn’t live up to expectations.
- StreamBright 8y agoCan you elaborate? I have used it successfully in many projects. People keep saying it has bad performance but I haven't seen any proof yet.
- TeMPOraL 8y ago"Nondeterministic" doesn't mean "bad", just that things can be OK until suddenly they aren't, and you can't really predict it a priori.
- kccqzy 8y agoSTM is indeed non-deterministic in performance, but non-determinism is basically a given in all concurrency problems. In the same vein you can also say locks have non-deterministic performance characteristics: I never know how long I'm going to wait when I'm trying to acquire the lock! In other MVCC scenarios such as databases you also don't know whether your final COMMIT will fail due to concurrent writes and you have to retry. Furthermore Clojure's STM in fact has an extra primitive called commute that is not present in Haskell's STM. It makes commutative changes even faster.
- lincpa 8y agoMVCC with the same principle as STM has been widely used by RMDB.
- dustingetz 8y agoNever used Lisp, but huge Clojure user, the real innovation is the immutable data structures: RICH HICKEY: Ok, so, problem number one on that list was place oriented programming. Absolutely, this is the problem. Almost all the programs I wrote, lots of the things on that list were multi-threaded programs, you know, they're crazy hard in C++. Just impossible to get right, when you adopt a normal mutability approach, you know, mutable objects. So, this is the number one self-inflicted programming problem. It seemed, you know, clear to me that the answer was to make functional programming and immutable data the default idiom. So the challenge I had was, were there data structures that would be fast enough to say, "we could swap this for that". And the objective I had, the goal I had was to get within 2x for reads and 4x for writes. And I did a lot of work on this, this was actually the main research work behind Clojure, was about these persistent data structures. Eventually I found...you know I looked at Okasaki's stuff and, you know, the fully functional approach and none of that gets here. And then I found Bagwell's structures were not persistent, but I realized could be made so, and they just have tremendously great characteristics combining the persistence with the way they're laid out, the way memory works. They made it. They made this bar, and I was able to get my friend to try my programming language. You know, we (?) have large library of pure functions to support this, and, you know, immutable local bindings. Basically if you fall into Clojure, your first hurdle is not the parentheses, right? It's this, this functional paradigm, everything is gone, there's no mutable variables, there's no state, there's no mutable collections and everything else, but there's a lot of support, there's a big library. You just have to, you know, sort of learn the idioms. So I think this was straight-forward, the critical thing that's different about Clojure is, by the time I was doing Clojure, the people who invented this stuff had adopted a lot more, right? I think most of the adherents in the functional programming community considered functional programming to be about typed functional programming, statically typed functional programming is functional programming. And I don't think so, I think that this is, you know, this falls clearly in the 80/20 rule. And I think the split here is more like 99/1. The value props are all on this side, and I think Clojure users get a sense of that, they get a feel for that. This is the thing that makes you sleep at night. https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/EffectivePrograms.md https://github.com/matthiasn/talk-transcripts/blob/master/Hi...
- 8y ago
- jlarocco 8y agoIt's kind of a trick question. Clojure pulled together a bunch of ideas from other languages and packaged them on the JVM. I'm not sure any single feature is particularly innovative. Lisp is well known for its ability to adopt ideas from other languages, and most of the important Clojure features (immutable data, transactional memory, etc.) were already available for Common Lisp and Scheme, either built-in or as libraries. My guess is that most Clojure users came from Java rather than another Lisp. Moving from Java is an obvious win (IMO), but as a CL user I don't see much reason to use Clojure.
- xiaq 8y agoScheme and CL have immutable data structures, but not persistent data structures.
- jlarocco 8y agoNot built-in, but there are libraries.
- drcode 8y agoBut afaik most immutable, persistent data structure libraries in other lisps either (1) had poor performance or (2) were developed after clojure and borrowed from clojure.
- chrisseaton 8y agoIsn't changing the head of a Lisp lisp by referring to the same tail from a new head an example of a persistent data structure?
- drcode 8y agoI think you're referring to "association lists" which definitely predate clojure and are definitely a persistent data structure and very cool in their own right. However, their performance profile is pretty poor (i.e. O(n) lookups) and are therefore rarely used in modern lisp programming anymore, to the best of my knowledge.
- axelrosen 8y agoAs a Lisp dialect it isn't that innovative besides a few syntactic improvements [0]. I'd gladly use Common Lisp instead if it could do something like ClojureScript. But by design it'd be hard to pull off. Like a good politician Clojure is pretty unimpressive in of itself, for any given characteristic, someone has a better take. But as a whole it's one of the few sensible choices out there. [0] I feel like they're generally underrated. Adding [] {} and #{} might not seem like much, but when writing DSLs they really do make all the difference.
- fiddlerwoaroof 8y agoParenscript is pretty close, as is js-cl. The issue is mostly that no one has written something like figwheel or shadow-cljs yet.
- axelrosen 8y agoNever heard of js-cl, but Parenscript definitely isn't. It's a glorified s-exp notation for javascript. ClojureScript doesn't compile to plain js. It maintains a lot of it's characteristics at run-time. And this is possible because Clojure does something very similar on the JVM. This in turn enables you to write code targeting both platforms without too much effort. WISP is a little more like the Parenscript of Clojure (though it's written in javascript itself) https://github.com/Gozala/wisp/blob/master/doc/language-essentials.md https://github.com/Gozala/wisp/blob/master/doc/language-esse...
- fiddlerwoaroof 8y agojs-cl is a (still-partial) Common Lisp implementation in JavaScript. https://github.com/jscl-project/jscl/blob/master/README.md https://github.com/jscl-project/jscl/blob/master/README.md Parenscript is a bit more than just a glorified s-expression wrapper for JavaScript: it also implements a lot of the core CL macros (defun, let, lambda, etc.) in ways that are close to the CL semantics. It’s limited by the fact that it doesn’t want to have its own runtime: so, while there is some degree of source-level compatibility, it doesn’t have things like restarts and CLOS that would require runtime support (although, there is a library called the Parenscript object system that provides some degree of source compatibility with CLOS.
- hardwaresofton 8y agoOutside of applying the research of persistent immutable data structures (which I think is from the Okasaki paper[0]), I think the most innovative part of Clojure is the fact that it's actually used -- they've managed to build a community and ecosystem with high quality packages and buzz around lisp. I don't pick Common Lisp/Scheme/Racket despite desperately wanting to because IMO Haskell has a better package ecosystem in my eyes, which is saying a lot. For example, try and find a HTTP server (by far the most common usecase for new projects IMO) that is both multi threaded and async IO capable (i.e. maximally using every core) -- it's surprisingly difficult, I found decent seeming libraries that did either-or, with varying levels of polish and paradigms involved. I personally prefer CL to Clojure but I just can't imagine trying to convince an enterprise to use Common Lisp these days especially since I can't even really convince myself... Clojure would have the same problem but the ecosystem + buzz is the differentiator in my mind. [0]: https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf https://www.cs.cmu.edu/~rwh/theses/okasaki.pdf
- kccqzy 8y agoBy the way Okasaki not just has a paper, but a whole book on that topic. It has code examples in ML and Haskell. It's really nice if you want to learn to design persistent data structures.
- bcherny 8y ago+1 Okasaki’s book is a great reference. I’ve personally given out a few as gifts. https://smile.amazon.com/Purely-Functional-Data-Structures-Okasaki/dp/0521663504 https://smile.amazon.com/Purely-Functional-Data-Structures-O...
- hardwaresofton 8y agoI just double checked and I think the link I posted is to the book -- I thought it was just one of the papers but that PDF is the actual 160 page book that was his thesis. Unless I'm misunderstanding, and book != thesis. [EDIT] - Looking through the Amazon listing, it looks the book is certainly not just a republish of the thesis... Looks like I have even more reading to do
- drcode 8y agoLots of user names with 4-6 characters in this thread- Definitely an HN topic of yore!
- kgwxd 8y agoI think the Sequences abstraction[1] is a pretty important one. I'm not sure it's unique to Clojure though, I have no other practical Lisp experience. [1] https://clojure.org/reference/sequences https://clojure.org/reference/sequences
- nickik 8y agoI think people here are making a lot of good points put I want to be a bit more specific. I don't have a lot of experinace with others lisps so please correct me. - The EDN (https://github.com/edn-format/edn https://github.com/edn-format/edn) data format is a further development of the code is data idea. 'Tagged Literals' are interesting feature and used in Clojure to make code shared between different Hosts, mostly JS/JVM. - Transducers are a new interesting features that are fairly unique to Clojure (https://clojure.org/reference/transducers https://clojure.org/reference/transducers) - Reducers (https://clojure.org/reference/reducers https://clojure.org/reference/reducers) - Clojure Multimethods are different from CLOS in CL and one interesting feature are stand alone hierarchies. Some people would maybe call this an step back from CLOS. https://clojure.org/reference/multimethods https://clojure.org/reference/multimethods - Concurrency primitives like Agents and Refs (featuring Software Transactional Memory) are fairly unique to Clojure. - Metadata. In Clojure most types can have metadata attached, meaning data that flows threw the program with your data but does not effect things like equality or size. - Protocols are dynamic single dispatch system - spec. Clojure Spec is a core part of Clojure now and used internally as well. Its a type of dynamic specification system and not like most systems of this type (https://clojure.org/guides/spec https://clojure.org/guides/spec) Some more information here: https://clojure.org/reference/lisps https://clojure.org/reference/lisps
- jwr 8y agoI think I am qualified to answer this: I wrote reasonably complex systems in Common Lisp before I gradually moved to Clojure several years ago. I have written several fairly large apps and systems in Clojure and Clojurescript (this includes https://partsbox.io/ https://partsbox.io/ as my current project and apps like an e-commerce search engine processing hundreds of requests per second for many years). I used to think Common Lisp was a fantastic language, but I always tried to keep an open mind remembering the Blub paradox. Then I started working with Clojure and after the initial friction (some things were just plain annoying in the beginning) things clicked for me. It was, quite simply, a much better language. The major improvements over Common Lisp for me were: 1) immutable data structures: these days I can't even imagine dealing with code that mutates data in-place, 2) a great approach to concurrency and parallelism (it's really difficult to get yourself deadlocked in Clojure), 3) Rich Hickey coming out every year or so with a solution to yet another problem (core.async, transducers, spec), 4) really flexible data structures. I know there are many CL advocates who will try to point out that CL has all these things. But these will be the same people who will be annoyed when Java programmers point out that Java has all these things, too. It's just a matter of friction, elegance and ease of use. One additional factor which is often glossed over is Clojurescript. Most software these days exists in some form in the browser, too. Being able to use pretty much the same language (cljc files can be compiled both server-side and client-side to Javascript!) on both sides brings many advantages. People sometimes ask me if I miss CLOS or the MOP. Not at all. It's a great set of concepts, worth learning (the green book makes for great reading). But I found that larger systems using CLOS were really difficult to understand and follow (just following the code flow is a nightmare if you have a lot of multimethods), and systems that used the MOP in any but the most basic ways were intractable without a debugger. Besides, please see above what I wrote about immutability: I'd much rather have immutable data structures. Clojure's emphasis on functions and data, while it may be based in the 60s, is one of the really good ideas. And Clojure is really, really good at tackling complexity, it's just not apparent in the language design. While other languages focus on syntax sugar, Clojure's focus is on getting things done on a large scale. You don't see that, but things like namespaced keywords, clojure.spec, pre/post conditions, maps, sets, all play together to allow you to create extensible and reusable code. Also, it's easy to discount certain solutions in Clojure as "also existing" elsewhere, but without actually using them in real systems one often doesn't see the full advantage. Transducers are a good example: I think they are under-appreciated and under-utilized. Common Lisp veterans will laugh and say that SERIES did the same thing back in the 80s. But SERIES was all about optimization and anyone who actually tried to use it will have stories to tell about how easy it is to use. Transducers, on the other hand, if used to build data-processing pipelines processing Clojure maps with namespaced keys, are an elegant and efficient tool for building composable systems. Plus, once you've coded your pipeline using transducers, it's a snap to parallelize it. Looking at it differently: to "get" Clojure one has to understand that there is no silver bullet: no single revolutionary "feature". Instead, the gains come from tiny improvements all over the place: immutable data structures, good built-in library for dealing with them, core.async, transducers, spec, Clojurescript, not having to convert to JSON or XML on the way to the client, re-using the same code on server-side and client-side, and more. In practical terms, I would never be able to write and maintain by myself the system I'm currently working on (https://partsbox.io/ https://partsbox.io/) without Clojure and Clojurescript. It isn't impossible, but I can't imagine tackling the complexity in a comparable time frame. I can't imagine going back to Common Lisp. I sometimes have to look at the code I've written in CL, and it looks clunky. Especially place-oriented programming (setf all over the place) is something I really really don't want to go back to. It's a nightmare, particularly if you intend to have any kind of concurrency. I still try to keep an open mind, remembering about the Blub paradox. I make it a rule to regularly check and learn about new languages. There are some which I found really good for certain types of applications and which I would use instead of Clojure in certain cases (Elixir is a good example). I still haven't found anything comparable which is a general-purpose language, especially if you consider the client-side story — but I'm checking all the time See also my answer to a similar question posted on Quora several years ago: https://www.quora.com/What-do-veteran-Lisp-programmers-think-of-Clojure/answer/Jan-Rychter https://www.quora.com/What-do-veteran-Lisp-programmers-think... Also, as a general observation: most (not all, but most) criticism of Clojure seems to be written by people who did not write anything significant in it, and much of that by people who simply do not write large software systems at all. Reading many discussions, I gloss over most comments, as they are simply beside the point and not even worth addressing.
- ledgerdev 8y agoClojure is radically practical :)
- deepaksurti 8y agoVsevolod Dymokin, a known name in the CL Community, especially for his work around NLP in CL has posted a detailed article on his views about Clojure. [1]. Worth a read. FWIW, when I worked in Clojure in it's early days, I disliked when it dropped into Java stack traces and dealing with Java exceptions made dealing with Clojure REPL not a great experience. I don't know the state of things today. [1]: http://lisp-univ-etc.blogspot.com/2011/11/clojure-complexity.html http://lisp-univ-etc.blogspot.com/2011/11/clojure-complexity...
- harperlee 8y agoIt is still far away from CL conditions, but clojure 1.10 has improved error messages A LOT through spec (a sort of optional typing system), and the plan is to improve it even better (cryptic error messages have been for some time the top issues in the yearly community feedback poll).
- lincpa 8y agothe best innovative: Clojure is a functional programming language based on relational database theory. ``` Clojure -> DBMS, Super Foxpro STM -> Transaction,MVCC Persistent Collections -> db, table, col hash-map -> indexed data Watch -> trigger, log Spec -> constraint Core API -> SQL, Built-in function function -> Stored Procedure Meta Data -> System Table ``` I don’t care about static or dynamic types, nor about FP, LP, or OO. For me, they are overly complex, unreliable, and unscientific. I think they are very bad and upset me. The production methods and business management ideas of large industries are also more mature than FP&OO. I have used them as programming ideas. I think that RMDB is the simplest and most reliable in theory and practice, and it is the most rigorous, long-term, high-stress test in critical situations. Before using clojure, I was a Foxpro programmer. I used clojure as a super Foxpro, and I also used it successfully in the field of WebApp and R language mixed programming. I will continue to apply this routine to the AI field in the future. The main development goal of clojure is to write the database. The development idea is actually from the database, not the FP. https://github.com/linpengcheng/PurefunctionPipelineDataflow https://github.com/linpengcheng/PurefunctionPipelineDataflow
- flavio81 8y ago>I don’t care about static or dynamic types,(...) I think that RMDB is the simplest and most reliable in theory and practice But... RDMBs are often statically typed (you specify the column type when creating it), and strongly typed (they often don't do auto-conversions of data types.)
- robto 8y agoI think their point is that it's the ability to express relational algebra in a natural way that's important, and the static/dynamic types thing is orthogonal to that.
- lincpa 8y agoWith reference to the database, as long as I use spec to strictly define (standardization) the core data model, I can ensure the correctness of the system. I've turned the traditional work of ensuring code correctness from in-code type system validation to data self-validation. Turn the work into verifying the core data model instead of validating the input and output data types of the function. A system requires only a few core data models, and development is built around the core data model. Persistent data structures ensure that the modification of the immutable big data model are high performance and memory efficient. In addition, using my pure function pipeline data stream (https://github.com/linpengcheng/PurefunctionPipelineDataflow https://github.com/linpengcheng/PurefunctionPipelineDataflow) makes debugging, parallelism and extension very simple.
- pfdietz 8y agoMy comments from Reddit threads: "I have not used Clojure professionally, but I welcome it, and applaud the effort that has gone into its creation and development. It's being used to solve real problems for real customers, and supplying jobs for those wanting to work in a Lisp family language. I also have a personal fondness for the immutable data structure work. Is it perfect? Nothing is perfect. I'd rather focus on the wins than lament blemishes." and "Not all of us CL people are like that, even the language lawyers who read the standard for entertainment. :) I find a lisp that explores a different part of design space to be inherently interesting, btw. The constraints surrounding Clojure are different from those around CL, so design choices have been different. The lessons learned when these choices collide with real world users cannot be obtained in any other way."