Saturday, November 2, 2024

Don't Try to Program in Lisp

A comment on my previous post said,

The most difficult thing when coming to a different language is to leave the other language behind. The kind of friction experienced here is common when transliterating ideas from one language to another. Go (in this case) is telling you it just doesn’t like to work like this.
Try writing simple Go, instead of reaching for Lisp idioms. Then find the ways that work for Go to express the concepts you find.

That's not at all how I approach programming.

A friend of mine once paid me a high compliment. He said, “Even your C code looks like Lisp.”

When I write code, I don't think in terms of the language I'm using, I think in terms of the problem I'm solving. I'm a mostly functional programmer, so I like to think in terms of functions and abstractions. I mostly reason about my code informally, but I draw upon the formal framework of Lambda Calculus. Lambda Calculus is a simple, but powerful (and universal) model of computation.

Programming therefore becomes a matter of expressing the solution to a problem with the syntax and idioms of the language I'm using. Lisp was inspired by Lambda Calculus, so there is little friction in expressing computations in Lisp. Lisp is extensible and customizable, so I can add new syntax and idioms as desired.

Other languages are less accommodating. Some computations are not easily expressable in the syntax of the language, or the semantics of the language are quirky and inconsistent. Essentially, every general purpose fourth generation programming language can be viewed as a poorly-specified, half-assed, incomplete, bug-ridden implementation of half of Common Lisp. The friction comes from working around the limitations of the language.

2 comments:

Hexstream said...

"inconsitent" should be "inconsistent". :)

Mark Safronov said...

While I have been learning Lisp and Haskell, the difference between these two and the classical imperative style was how I looked at the program.

In the classical imperative style program is a list of instructions which mutate a state machine in the background. It's a natural representation of what's actually happening in the hardware - CPU executes instructions one-by-one which change (destructively) the values in memory cells.

Lisp and Haskell operate on an infinitely higher level. The program in both of them is an expression which you reduce to a value. Side effects in the process of this reducing are nuisance.

These two are super fundamentally different world views IMHO.