Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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.



Here is something from Clojure that stuck with me as particularly elegant:

The -> macro.

  (-> {}
      (add-person 'servbot)
      add-age
      add-info
      add-to-db
      notify-status-by-email
      log-user-addition
  )
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

  (-<> {}
      (add-person 'servbot)
      (add-age 21 <>)
      (add-info 'servbot <> 21)
      (add-to-db 'my-db-handle 5432 <>)
      notify-status-by-email
      (log-user-addition 'dev 'email <> 'paint-by-numbers)
  )
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.

Edit: Update for formatting.


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.

  (as-> {} <> 
      ...
      (add-age 21 <>)
      ...)


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.


You don't need to do CPS transformations if your language supports first class continuations. Lookup `call/cc`


Indeed, but Common Lisp doesn’t!


I remember being struck by a snippet of pseudocode in a discrete mathematics textbook[0]:

https://pastebin.com/L2dwawgu

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.

Edit: Traded formatting for pastebin


Inline some data structure. Json, interestingly, embeds trivially in lisp. Not so much in Java. Especially once you learn the quasi quote.


I would love to see the reverse. Ive never seen a Java codebase that I thought was pleasant to work with, but maybe I'm just not looking hard enough.


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.

Where are the good Java codebases hiding?


I agree that the Android APIs are not good.

Have you looked at JDK itself?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: