In my opinion, this turns out to be a pretty major win. Code is still data, it's just that this data is a mix of lists, vectors, and maps, and now you can type associative data structures into your code as easily as you can lists. Hash tables in vanilla Common Lisp are a nightmare (there is a nice library that at least gives a Clojure-y initialization option via Reader macro), and a glance at the Racket documentation suggests the story there is probably not much better.
Clojure code in the wild uses the destructuring on maps a lot like, e.g. Haskell code uses pattern matching, and Spec is an interesting core library aimed at allowing libraries to insist that keys be present in maps and so on.
Anyway, I had occasion to interact with some Common Lisp code I'd written several years ago, and I was struck by how annoyed I was at it for not being Clojure. Part of that is the Lisp-2 issue, but I also really missed how lightweight and easy Clojure maps are, and how easy they are to use for control flow. (I will say that Clojure's clunky recursion annoys me, but much less than trying to deal with Hash Tables in CL)
Also, and I know you say you don't care about Java, but ... sometimes you have to interact with some annoying outside system (like, a database or a web browser), and there is a high-quality Java(Script) library that makes this task trivial and lets you work on what you want!
For original asker, see here for more details: https://clojure.org/reference/data_structures
I seriously disagree with such a statement.
Also, i feel confused that a lisp being a Lisp-2 could be an "issue". Separate namespaces for functions, symbols, classes, labels and so on is great, because they dramatically simplify naming things, which is one very important task for writing clean, readable, maintenable code.
It was an okay learning journey, but it left me hungering for an easier FP language, and it also solidified my intuition that simple is both easy and hard at the same time, and Lisp is simple.
“First-class”, you keep using that word. I do not think it means what you think it means. See here for the details: https://en.wikipedia.org/wiki/First-class_citizen . tl;dr: First-class-ness is about semantics, not syntax. And, while every language (including Racket) is broken in some ways, it's not broken enough for associative data structures to be inexpressible in it.
> There's a literal syntax for them.
Why does this matter in a language with macros anyway?
> Why does this matter in a language with macros anyway
If you don't have this, you end up with a bunch of read table syntaxes for the same thing. These usually don't play nicely together. See Common Lisp libraries (since CL doesn't provide this syntax in the standard) for all the subtly incompatible hash table read syntaxes and printer implementations you can stomach.
For many of us, Clojure(Script) is the right tool: a balance of performance, ecosystem interoperability, expressiveness, etc. on the platform we're targeting.
It's the same question I make myself, since after learning Clojure here I am, still using Common Lisp happily ever after.
Well, if you think that data should be immutable by default,
if you really need readymade syntax sugar for hash table and the likes,
if you don't have any need for object oriented programming, not even once a year, and if you particularly don't feel any appeal for what is by far the most advanced OOP system out there (CLOS),
if you love the Java ecosystem and need to be reminded of the J2SE libraries by using them directly all the time to do things other languages have built inside their own stdlib (but Clojure does not),
if you don't feel wrong knowing that your code won't be compatible with the .NET CLR (or other platforms) without rewriting substantial parts, despite the language still being called "Clojure",
if you don't know that basically all you can do with Clojure, including talking to Java (and also C) libs, and all sorts of concurrency things, you can also do with good old, high performance Common Lisp...
... then welcome to Clojure! Clojure is easy to learn, fashionable, well supported, and popular.
I guess that if you are into developing single page applications, Clojure can be a neat choice.
I do, however, find it easy to learn and that's a good thing.
On the other hand i am not really knocking down Clojure. If somebody wants me to do a project that requires interacting with lots of Java classes, I'm really glad Clojure exists, since it liberates us from plain Java. I am also glad that it's a good "gateway drug" to Lisps in general. I'm also glad that ClojureScript exists, perhaps this is the best part of Clojure.
But Clojure is not really my cup of tea. I want wide options for mutable data (for performance reasons). I want multiple paradigms, including a powerful OOP system. I want easy recursion with tail call optimization. I want explicit, detailed error messages, etc.
I sincerely thank Hickey for liberating us from Java and plain Javascript. I think that if Clojure was pitched more as substitutes of Javaxx and less as "the improvement over Lisp", many of us Lispers would be happy. As I mentioned, it isn't an improved Lisp; it is a different language with a different (valid) philosophy which some will like.
How many libs do we really need? So far i have found all libs I needed for Common Lisp. Many of them have high quality, at least in the sense that the code is easy to understand.
Most needed stuff is there - db access, key/value store, cryptography, authentication, html templating, JSON, xml, web servers, software transactional memory, parallelization, compression, networking, foreign interfaces, music, midi, all sorts of data structures, and of course tons of AI related stuff. This is not like NPM where there is a lib solely dedicated solely to left-padding a string, and when you take down this lib the whole ecosystem collapses big-time (true story).
Also, just as Clojure can easily call Java code and thus have access to the huge and mature Java lib ecosystem, also Common Lisp can very easily (see 'CFFI') access the huge and mature C lib ecosystem, mind you, and this feature is leveraged a lot in CL. This also has performance benefits, since tuned Lisp code is as fast as tuned Java code, but C can often go faster. With ABCL (JVM implementation of Common Lisp), you can even call Java libs and C libs in the very same source code, which I find amazing.
You might spend sometime learning it out of curiosity, but you will never use it
The languages I used, are ones I had to use, either because they were the only option, or clearly the best option for my solution (C#, VB.Net, Powershell, SQL)
Clojure will never be your only option, and .. it being the best option is highly subjective
I tried to like Clojure, because of all the blogs and talks, and the reputation of it being a smart language for smart people (I obviously, wanted to belong to this group, and still do) .. but for my work, and use cases (Business Intelligence), it will never be the best option, or the only option
The same list that include Clojure, for me also include F#, D, Dart, Ada 2012, Idris, Julia, Rust .. I am sure since you asked this question, you have your own list too .. and you know, nothing will really work to motivate you
Now, when I'm working on a team... I must tell you I live in Florida and if I've ever met another Clojure/Lisp programmer in meatspace I'm not aware of it (and I'd be surprised). In fact, most of the Java developers I work with only really know Java (and some are helpless without Eclipse). So recommending anything that isn't Java probably wouldn't be wise. So, yea.
There's a difference between "best tool for the job" and "most widely used tool for the job" at this moment in time. People's habits sometimes take years or decades to break (if they ever do).
Amen. Learning is best a journey of desire, not compulsion.
I'm somewhere between indifferent to unhappy that it runs on the JVM, but it's not a blocker for me. And as someone else mentions, it means there's pretty good access to the Java library ecosystem.
1. Declare the classes you want to work under transactional memory as transactional... by wrapping them in such a way:
(transactional (defclass ...))
2. Whenever you need to do a STM transaction, just wrap the critical code within (atomic): (atomic (do-stuff ... ))
Is it hard? Nope. The above example is one easy way to do it in Common Lisp, using the STMX library, which of course you can download, compile and load with one line of code: (ql:quickload "stmx")
So yes, it is easy under Clojure, but not only in Clojure.Lots of support
Great interactive workflow (with Emacs, Intellij, or Atom)
Data oriented (Most of your code are pure functions making
simple operations on datastructures)
It's also a nice Lisp, tho not as pure or quite as powerful as others.
But I'm not very much up-to-date on anything new in the past few years, and I was never a guru anyways, so maybe there are better pitches.
* it doesn't do tail call optimisation unless you explicitly mark the self-call using by using recur (the lack of implicit TCO is a JVM limitation) * it doesn't use macros as much, although they are they're there and still used pretty often * it has language literals for the built-in data structures that look odd to other LISP'ers, e.g. {...} #{...} [...] * it's error messages are ecosystem dependent, e.g. Java stack traces for Clojure or and JS ones for ClojureScript
+ ClojureScript: allows you to write Clojure for any JavaScript platform (web, ReactNative iOS/Android, node.js) while writing 97% the same language excluding any platform-specific differences between the JVM and the JavaScript runtimes (V8, JavaScriptCore, etc)
+ piggyback on the entire mature+stable+performant JVM ecosystem of
... + tools (Maven >> npm, cocoapods, et al)
... + libraries (Netty, JodaTime, etc)
Not sure how usable the .net part is.
Do you want to be sold on it? Is that what you want your interactions on this site to be?
Since I achieved my aim and stimulated some useful and on-topic discussion, yes, this is what I want my interactions on this site to be. Thanks for asking.