Beside the REPL, another impressive feat of Common Lisp is meta-programming. You can write software to write software. Say what? Yeah, that was my initial reaction too, but Common Lisp’s macro system allows you to write functions that return code snippets. It completely redefines the word. Or more accurately, re-redefines, since Lisp is much older than MS Office, which is what most people associate macros with, sadly.
The article could be improved by including an example. Pick one in which Java makes the problem to be solved tedious, verbose, repetitive, or error-prone and where Lisp macros do not. Bias the example as much as possible to a problem where Lisp can shine. It should, however, be a real problem most programmers are likely to face in some form.
Then present the source for both solutions.
This approach would even help those who don't use Java regularly because they could try to implement the same functionality in their language of choice and compare it the the Lisp implementation.
So the threading operator is exactly what you ask. It inserts the results of the previous expression as the first argument as the first argument as the next expression. Note this still supports situations where an expression can take more than one argument.
Additionally, there is the ->> operator which inserts the previous result as the last argument in the next expression and some a library that includes the "magic wand" operator "-<>" ala
This particular set of macros seems entirely trivial until you use it, and then it changes your entire perspective of what functions do since your ability to express the computation pipeline changes completely.
The Clojure standard library has had the the 'as->' macro for a while which serves the same purpose as the "magic wand". It doesn't need to use '<>' as the identifier, but I usually choose to do so because I learned about the magic wand library before I learned about the 'as->' macro.
Implementing async/await. You can accomplish that entirely via macros in Common Lisp, whereas in Java you would need to do bytecode transformation via a javaagent (which, shockingly, I just discovered somebody has actually done: https://github.com/electronicarts/ea-async).
That being said, I write Java for a living, and I don't find it terribly verbose, outside of the lack of sum types, pattern matching, and typeclasses.
Isn't that really hard to implement correctly in Common Lisp? Your macro would need to perform a continuation-passing style transformation on arbitrary code that could involve jumps, error, etc.
So basically being able to run an arbitrary number of dependent, nested loops. Now imagine you want to run arbitrary code in the interior, rather than just incrementing a count.
It's a simple idea. And it can be expressed so succinctly in just a few lines of pseudocode in a freshman-level computer science textbook.
And yet I wouldn't want to touch this in Java. The lisp macro to write this isn't much more verbose than the pseudocode itself.
[0] Rosen's Discrete Mathematics and Its Applications, 7th e.
You're really underestimating the power of Java's boring workhorse methodology. If you're looking for love there's a lot of other languages that are more pure and more beautiful for certain use cases.
However, there's a reason Java is in the top 3 most popular languages. Its pragmatic, it scales, it plays nice with tooling and the language itself is pretty passable.
> However, there's a reason Java is in the top 3 most popular languages. Its pragmatic, it scales, it plays nice with tooling and the language itself is pretty passable.
I wonder if those are true reasons. I currently believe in the following set of reasons, in the order of importance: runaway feedback loop of popularity (popularity -> jobs -> popularity), JVM is cross-platform, low cognitive effort per line of code written.
I'm not asking for anything fancy - just an example of a Java codebase that is "good" for whatever definition of "good".
I'm currently dabbling in Android development, and the few Java libraries I've dealt with, especially Android's own APIs, have been a thorough exercise in frustration, to put it mildly.
The article could be improved by including an example. Pick one in which Java makes the problem to be solved tedious, verbose, repetitive, or error-prone and where Lisp macros do not. Bias the example as much as possible to a problem where Lisp can shine. It should, however, be a real problem most programmers are likely to face in some form.
Then present the source for both solutions.
This approach would even help those who don't use Java regularly because they could try to implement the same functionality in their language of choice and compare it the the Lisp implementation.