Hacker News new | ask | show | jobs
by spain 4106 days ago
As someone who thinks Lisp is pretty cool and uses Emacs to study it and is about 100 pages into SICP: I still don't get it. Common Lisp macros went entirely over my head too. A programmable programming language? Aren't all languages like that? I've only been programming for a couple years so I'm afraid I might not recognize the value of Lisp until I use more of the "less powerful" alternatives.
5 comments

The principal data structure of Lisp is a list which is written like this: (a b c d). Like the article mentions, when you see Lisp code you're in fact reading the same list syntax, only that, when the list itself is not quoted, the "a" is evaluated as a function, which is why (+ 1 2) behaves the way it does. If you quote the list by saying "'(a b c d)" then it is a list of symbols, so "'(+ 1 2)" does nothing.

Hence, Lisp code is made of nested lists. When you think further about it, it means that Lisp metaprogramming facilities may do things just with plain list manipulation functions! So it's not about metaprogramming itself, it's that it's incredibly easy. This is what people refer as "code as data" and "homoiconicity" and so on.

Lisp "advocacy" often touts the power of macros in an abstract and unconvincing way. Persuasion by explanation isn't very effective. I'm not very interested in persuading others that Lisp macros are necessary, and there are many languages I like to use that don't have macros. However!

Yes, all programming languages are programmable. But Lisp tends to be unlimited in its programmability, in almost the same way that Unix is: if you have root, you can change anything. I'm pretty sure that in most Common Lisp systems, you can redefine large parts of the compiler at runtime. And so on.

Syntactic macros are just one part. They can be extremely handy. Lots of Lisp systems use them well. Random examples: the DEFSYSTEM macro of ASDF; the DEFINE-EASY-HANDLER macro of Hunchentoot (a Common Lisp web server); the (controversial) LOOP and ITERATE macros; etc.

Another somewhat random example: Movitz was (is?) a project to write an x86 kernel in Common Lisp. It actually included its own compiler. It defines a lot of macros for instruction definition [0] and uses them in code that I don't understand anything of [1] but is probably very clear to someone versed in assembly.

Recently I've been trying to add some nice logging to a JavaScript program, and it's a typical scenario where the normal syntax is just annoying enough to make the code ugly and hard to scan—if I had macros, I could invent some other syntax.

How to use macros is a tradeoff that I guess comes with Lisp experience, but they can be a powerful escape when the standard syntax is annoying, and a way to define your own DSLs without restriction.

[0]: https://common-lisp.net/viewvc/movitz/ia-x86/def-instr.lisp?...

[1]: https://common-lisp.net/viewvc/movitz/ia-x86/instr-add.lisp?...

> A programmable programming language? Aren't all languages like that?

How would you write a program to write a program? How can you use this generated program in your other code? It's really hard to do with a lot of programming languages, even those that have eval like JavaScript, so it never occurs to people that something like a template system or a code translator/DSL should be trivially easy to write.

I found the "Little Schemer" an enjoyable tour on exorcizing the power of lisp. Depending on how far down the rabbit hole you want to go there are a plethora of information in various AI memos as well as the READscheme web resource with the original LAMBDA papers (readscheme.org) which most certainly worth PRINTing if anything to get primed for SiCP.
Lisp doesn't have pattern matching. With optima[0] it does.

Lisp uses prefix notation. With mexpr[1] it uses infix notation.

And so on.

[0] https://github.com/m2ym/optima

[1] https://github.com/tmccombs/mexpr