If Lisp is so great
mihaiolteanu.me
mihaiolteanu.me
I read the whole article and its a lot of words to simply say: There are a lot of factors at play. It could be a mix of those factors.
Beyond that the article does not seem to give any specific insights. It provides many loose analogies to show how something good might not be not mainstream in other walks of life. But it does not go on to elaborate what it is specifically about Lisp.
So I guess I am trying to say I don't know what to do with this article. The talking points are all common sense. And there's nothing specific about Lisp I can learn from this article.
Is he saying that English is better than Chinese? Or that using a different kind of keyboard for Chinese would be better? Or that the author believes that only English uses the Latin alphabet?
What point is he trying to make about golden crowns and Caesar having nothing to conquer? That using Lisp would be pointless if everyone used Lisp because it's only useful for gloating about using the best language?
For that matter, Common Lisp had what was probably the first modern language specification, that, as much as it pretended to be machine independent, was carefully designed to be implementable on the 32-bit microprocessors that were then coming online. There was a time when I thought Java was the first programming language to be specified by adults but know I know they were following in the footsteps of Common Lisp.
After all these years we still don't have macro assemblers as good as what the IBM 360 had even though we now have architectures that have enough registers that it would be reasonable to pass a register name as an argument to a macro like you could do in IBM Macro Assembler.
So that's a pretty impressive improvement--3x over 6 years--but I remember Raku being numbers like 4x or 5x slower than Python on benchmarks from the last few years, so by my very sloppy math it's still got to speed up by at least 2x or 3x to go to match Python.
It's also possible that there has been a ton of speedup in the last year-and-a-half since that benchmark, or it's not representative, but that's where I got the idea from.
[1] https://blogs.perl.org/users/sylvain_colinet/2023/01/benchma...
To your point, I recently measured the compile time of this raku module...
# speed (2020)
# use Physics::Measure :ALL; ...13s first-, 2.8s pre- compiled
# speed (2024)
# use Physics::Measure :ALL; ...4.4s first-, 0.9s pre- compiled
... so about a 3x speed up in the last 4 years.
Also raku has no GIL and has good support for hyper / race so can get a lot out of your 32 cores (if you want speed).
Another raku module to mention (Dan::Polars) connects to the Rust Polars library via FFI (thus getting Rust level execution speed since Polars a lot faster than Python Pandas via the underling Apache Arrow data structures) ... this takes about 2s for the raku to compile and about 15s for the rust cargo stack to compile ...
Having features of a given language don't make something a full or even partial replacement for that language.
"It's not what languages do, it's what they shepherd you to" - https://nibblestew.blogspot.com/2020/03/its-not-what-program...
I see what you did[0] here.
I'd grant that parser generators still suck, people still act like you're crazy when you say you want to be able to write one grammar and automatically generate not just a parser but an unparser. (I could do amazing stuff with Sphinx if only it supported RST output as well as schemaless RST.)
CASE tools in the 1990 could parse code, let you edit it in a GUI, and make a clean edit to the code (not mess up comments, whitespace, and the ordering of things which is only significant to your version control tools) like a professional programmer would. That's still like something that fell off a UFO.
You should totally be able to compose two grammars. I ought to be able to stick a SQL query right into the middle of program in Java or any other language and have it parsed to an AST. If parser generators were sane I could add
unless(X) { Y }
to a language like Java and add a method that rewrites it to if(!X) { Y }
and it shouldn't be more than 50 lines of code including imports and ceremony, just a patch to the grammar (AST objects ought to be code generated from the grammar) a simple rewriting function and telling the system where to find the grammar patch and the new function.Parsing Expression Grammars are a step in the right direction but for a PEG parser to be really revolutionary it needs a few features I've yet to see in one, in particular there has to be some easy way to specify operator precedence either numerically or with a set of statements like
Closer(*,+)
I am mostly disappointed w/ the PEG parser in Python because it falls short of revolutionary promises but you always get "fooled again" with parsing because people care about how fast their compilers are to the exclusion of almost everything else.I never had a chance to see proper CASE tools, my education started in 2000.. java/uml took the light and the few environments I saw were very very subpar (post IBM, eclipse based, rational suite).
The grammar composition is still a big open problem, I think Lawrence Tratt tried to attack it (maybe this https://soft-dev.org/pubs/pdf/diekmann_tratt__parsing_compos... ?) but concluded it was still fragile/difficult.
That had almost nothing to do with syntax and almost everything due to lobbying.
HP was not an "approved" calculator for all manner of standardized tests while really shitty TI ones were.
HP calculators were everywhere in my engineering department from 1988 to 1992 (the HP-28S and then the HP-48SX went through them like wildfire).
The problem was that places like the College Board allowed calculators in 1994. That meant that an "approved" list of calculators appeared and for a long time the HP programmable calculators were considered "too powerful" and disallowed. That "approved" list propagated to other things that used calculators in official capacities.
That absolutely killed HP as the volume all went to TI since everybody bought TI calculators and nobody was going to then spend on an HP calculator that might not be allowed on your test.
By contrast, look at business and finance majors where lobbying didn't create an "approved" list--you will pry an HP-12B from their cold, dead hands.
One thing that stands out about them is that they're all so happy. Try it. Search up a HN post about a Lisp. They'll be using words like "joyful".
So my theory is that while lisp may have plenty of technical merits, part of why it's so great is that it's typically being used by people who are having fun.
That's not to say that it would perform poorly if used under duress, but maybe there's some wisdom in not putting that experience that you enjoy anywhere near drudgery, lest it become contaminated.
We had a small group (~20 devs all together) that decided they wanted to do a lot with clojure. So they started several projects throughout the company and, for the most part, they all very much enjoyed using clojure.
However, as those projects shifted into maintenance mode and that group moved on to greener pastures, we were left with a bunch of projects that were inscrutable. The big issue we ran into is that lisp LOVES to give programmers the ability to metaprogram and programmers love metaprogramming. However, when it comes to maintaining a metaprogrammed monster... that's basically just learning a new language used by nobody but this single project.
The end result was that people dreaded taking charge of lisp projects. They were hard to ramp up on. Hard to maintain. And they had really strange and hard to diagnose bugs. We've since spent the money rewriting most of the projects in java. I believe there are 2 that were simply too big and complex to do such rewrites against.
My takeaway is that lisp is much like perl. When you know what you are doing it can be a lot of fun, but heaven help the person that has to later read what you wrote.
and (many of them) hate writing documentation.
> that's basically just learning a new language used by nobody but this single project
and there is no source to learn the language from. other than the "self-documenting" code, which often isn't.
I am not opposed to using abstraction. Sometimes abstractions are powerful. But the more abstract you go, the more effort you need to spend to make sure you communicated it properly to the rest of the team -- including its future members.
Rampant metaprogramming is not that common in Lisp codebases, and what of there is will tend to be pretty shallow, like bits of syntactic sugar here and there.
Do you have some example of the inscrutable metaprogramming?
One dev came up with their own macro that linked together the http client and json parsing into one magic macro which allowed them to also format the json, log it, and a bunch of other conveniences mostly for that dev. Unfortunately, the function was highly tailored to where it existed (with hard coded params and such). It's invocation ended up looking something like `(ht-j g foo 'log')` (because this dev also liked shortening everything).
Another example of this is some devs wanted to make a super generic data fetching... thingy... so they came up with this wild macro where you could feed in http urls and a custom configuration and it'd expose calls to that downstream services. It allowed for a sql like interface into several different microservices. Interesting in concept, impossible to maintain. That project was ultimately scrapped.
I was unaware of "the lisp curse" before my comment. This was just what my company experienced.
Feels like it is relative
If you spent whole life in C then anything sane will be joyful
The thing about Lisp is that when you get used to it, you realize how needlessly obtuse so much of programming is today. So much effort has been spent making programming harder and harder to understand.
At this point I truly think that if Lisp had won, the world would be quite a different place for the better. We live in a world where the average person thinks that a terminal emulator is an error window, and coding is something they identify as not being able to do. Lisp is so nice because when you understand the (extremely simple!) grammar, any vocabulary is correct. You just have to make sure that an implementation of that vocabulary is defined in terms of the vocabulary provided by the system. This is to say: the language let's you express things in the exact fidelity that you think them. That's why it's so appealing. I think that if Lisp had won, general programming would be as approachable as using a graphing calculator.
[0] FWIW I found it in the SICP lectures.
Someone please lead me into the wilderness.
Different people think differently. Having to decipher someone else's thoughts is less appealing that expressing your own.
Some people are great thinkers, and their thoughts-made-code are elegant. But there is no guarantee that your colleague who started a project that you join three months later is one of them.
The goal of programming on Lisp is to define a new vocabulary to further build on. If you don't like the vocabulary defined by your colleague, you can easily use (or define) a different one at the same level of abstraction.
It's not a goal of any reasonable Lisp developer to write as many macros as possible.
What macros are written don't have to be earth shattering new languages; it's okay to just make some syntactic sugar needed only in one file and whatnot.
I wrote an accounting system for my self-employed business activities. In the entire codebase, there is one macro:
time.tl:43:(defmacro def-date-var (name . date-range-val-triplets)
def-date-var defines a global variable whose value depends on the date. Not the current date, but the date established by context of a financial calculation. E.g. if we are adding a new transaction across the ledger, which represents an invoice to a customer, the code doing that would install the transaction's date as the date variable. Then all the date vars referenced will take on the value from that date. This is useful for things like tax rates and whatnot.Everything else in the program was done without custom macros. Of course macros from the programming language are used; you can't do anything without them.
I could have made a mini language for, say, defining an invoice. But nope, it's just normal syntax for constructing a new object.
You should almost never write a Lisp macro to do something a function can do. This is a FAQ for Common Lisp:
https://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part1/f...
- Never use a macro instead of a function for efficiency reasons.
Declaim the function as inline -- for example,
(DECLAIM (INLINE ..))
This is *not* a magic bullet -- be forewarned that inline
expansions can often increase the code size dramatically. INLINE
should be used only for short functions where the tradeoff is
likely to be worthwhile: inner loops, types that the compiler
might do something smart with, and so on.
[...]
- Don't define a macro where a function definition will work just
as well -- remember, you can FUNCALL or MAPCAR a function but
not a macro. The source code of the Viaweb editor was probably about 20-25% macros. Macros are harder to write than ordinary Lisp functions, and it's considered to be bad style to use them when they're not necessary. So every macro in that code is there because it has to be. What that means is that at least 20-25% of the code in this program is doing things that you can't easily do in any other language.
From: https://paulgraham.com/avg.htmlNetwork effects likely explain a big part of it. Many of the "popular" languages today aren't necessarily great languages and adopted for their technical merits. Often they were the only language available on an exclusive platform everyone wanted to develop software on. Other times it was because folks wanted to write a particular kind of application and there just happened to be this framework in this weird language that made the task easy.
We probably have more programming languages now than ever before but I think the market for new languages in the mainstream is relatively static. It shifts... but very slowly.
Currently liking lisp for exploratory programming and ML for precise communication of fully formed ideas to the machine.
Anyone happen to know a lisp/ML pair that target the same VM/IR for seamless interop between the two?
(in this context ML is metalanguage, ideally StandardML, though ocaml/miranda/haskell are the same sort of idea)
(sub (:&is-even = (sub (\n)
{([or] ([==] 0, n),
(is-odd (pred n:)))}),
:&is-odd = (sub (\n)
{([and] (not ([==] 0, n)),
(is-even (pred n:)))}))
{is-odd 11})()
https://www.codesections.com/blog/raku-lisp-impression/"There is only so much space available in a city."
Is there a limited number of possible LISP practitioners in the world?
Looking at the broader point: yes, there are a lot of factors to take into account, but perhaps we should be looking at the factors that specifically involve LISP.
The key takeaway of the essay is that: When someone questions why something supposed to be "best" isn't widely used, the answer is not solely technical. It also have sociological, philosophical, economic, and political aspects.
The essay is thus attacking the question form a different angle. Thanks for the kind words.
Lisp was by far my favorite language in college, but these days the idea of sloshing around in all those untyped s-expressions just gives me the willies.
The future I am trying to design is a language where traversal order is arbitrarily repetitive and arbitrary and corecursive and has term rewriting traversals.
I think algorithms are just reified traversal evaluation orders and joins - of algebra and mathematics.
Is this an unintentional misspelling, or an intentional one? That it’s italicized makes me think it’s an intentional reference or joke—if so, what is it?
Anyway, some other reasons:
* Baby ducks who can't get over the parentheses (which quickly become invisible to the eye, you read Lisp via its indentation).
* Baby ducks who can't get over too weird/big differences from C/C++/C#/Java/etc... like CL's compilation model.
* ML typing being /the/ fad these days.
* Low-level fetishism. I know a lot about this, since I've had my own C weenie phase (you know, the kind to spit on GC by principle) as a young university student, before turning smug lisp weenie ten years later; Tcl was actually my gateway drug into useful homoiconicity.
* Some hard technical limitations:
* No user accessible parametric deftype.
* No recursive deftype (so no typed lists/trees).
* Gimped hash tables (untyped, lacking literals thus read/write transparency).
* CLOS being bolted on instead of truly integrated in the language; would need a JIT and something like https://github.com/marcoheisig/fast-generic-functions on system classes to go fast enough, Julia kinda does this (but it hurts my eyes).
* Lack of LSP; no, SLIME/Sly isn't the same, as you're lacking lexical information that allows to complete/rename stuff.
* And hundreds of other rust spots sometimes fixed by extensions (e.g. gray streams, extensible sequences) or libraries (loop -> iterate, trivia), very often crutches in look and feel.