More importantly, would you please not start programming language flamewars on HN? What you posted here reads like a caricature of the kind that was tedious 15+ years ago. As a community, we've come pretty far in clambering out of that swamp, so I'd not like to fall back into it.
Things like Coalton [3] really make Lisp stand out. What other language is able to add Haskell-quality types to their language?
Lisp is not popular, so it doesn't have as much labor going into it, but for the work that does, remarkable results are achieved. Lisp does have a lot of the dubiously claimed power, but that power still requires reasonable engineering work to achieve—work that a lot of hobbyists are unwilling to do in their free 4 hours on the weekend.
[1] https://github.com/quil-lang/quilc
Can you clarify what Python and LISP software (with the same scope) are you referring to?
They have the role of taking general quantum programs (usually called "quantum circuits"), and translating+optimizing them for a particular quantum computer architecture (i.e., one that might only have a small number of supported quantum operations).
It's analogous to a language like C having a compiler (written in Lisp or Python) for ARM and x86.
Now as for my thoughts: every so often when Lisp comes up there is someone who asks 'give me some examples of companies which use Lisp/software written in Lisp' followed by someone giving some examples. That's all good and well but then someone chimes in with the... rebuttal? 'Well, if you have to stretch so much to give examples of Lisp being used that means that it's a dead language not worth using.' ...Or, well, some variation on that theme.
Of course I'm not saying your question is the lead-in to another exchange like this, but after seeing it a few times I get a bit tired of that back-and-forth and it makes me less eager to engage in discussion. I also don't really see the logic behind 'which companies use Lisp?' 'Here are companies that use Lisp:' 'Aha! If you have to list companies that use Lisp it means it's a dying, terrible language!' Imagine that exchange in a discussion of Rust or Python or Kotlin or whatever.
Anyway, sorry for the derailment, just had to get that off my chest. But yeah, Google Flights, ITA Software, just one example of CL in use at a larger player.
I really want to like it. Its interactivity is only matched by Smalltalk.
What are the problems I found? First, macros are nice. But they are difficult to write and potentially difficult to grasp. I think you should avoid them almost all the time.
Also, I found that regular Lisp (yes, I know with macros you can change that) is less readable than Python, for example. I struggle to read math with logic in Lisp (inwards-outwards) way more than left-to-right.
Also, the superior interactivity means you have an image. But when I create software I organize things in files, I run them from scratch. In Lisp everything becomes (or tends to become) kind of a stateful environment. It takes more reasoning to reason about current state.
I would say that Lisp is good at two things: DSLs and ast manipulation is way easier than in other languages. If you need that, it is nice. Also, highly experimental interactive programming to try ideas is good with this interactivity. However, creating a system where a level of interactivity for your needs can be created is not super difficult, so you can have a very interactive Python env. for example, except that the object system in Lisp is a bit more interactive. But, do you need that?
All in all, Lisp is a language I struggle reading, powerful for ast manipulation and DSLs, but the macro/DSL parts are what also prevents it from being easily picked-up by teams. In fact, I would forbid macros by default unless carefully approved for "regular" Lisp programming as done in most software products. It can obscure the code quite a bit.
I like Clojure, I like Janet lang and I like Lisps for embedding. Also, I do know the power of having a running server and being able to enter and live debugging it, but, is this practical? At the end you want a commit somewhere, a CI pipeline to be run to verify your software, etc. So I am not sure if when programming in Lisp one of the problems I find is that I should change my mindset but I am not successful at it.
Interactivity has nothing to do with an "image". An image is a dump of the memory heap. That's a feature found in several, but not all, Lisp implementations. There are Lisp implementation which support image-based development (like Interlisp). But I doubt that you have used that.
What many Lisp systems actually often are: they are interactive with a resident language environment. There are many examples for non-Lisp implementations of that idea: APL, BASIC, Prolog, Smalltalk, Python, Ruby, R, ...
Still, software in most Lisp projects is organized in files. Something like Common Lisp includes a compiler, which compiles files and a loader which loads files (compiled and source). But the Common Lisp runtime usually includes a compiler and an interpreter and one then can develop the application interactively while it is running. The code is still written in files.
> but the macro/DSL parts are what also prevents it from being easily picked-up by teams.
That's a myth. Actually macros are BEST used in teams.
Small teams of 5 to 100 people can easily define/use language extensions, document them and reuse them in their application software. Larger Lisp software benefits most from macro definitions, since they enable development of portable language extensions incl. embedded domain specific languages, without the need for low-level implementation hacking. -> the result is very compact user level code.
Actually I was unconsciously talking about the typical Common Lisp implementations I have used.
> Still, software in most Lisp projects is organized in files.
Yes, sure, but I am not sure the combination of image, promoting interactive development mixes well with do a git commit and typical CI pipelines. Interactivity encourages a flow where you "instantly see" results and experiment, whereas a compile-edit-runtests follows more naturally with more structure in test cases, etc.
Of course they have their uses, and their very useful use cases. But I do think they should not be abused and I also think they should be the last thing to use, when nothing else will work.
Unless one saves and load images, one is not using image-based development. All one is using is the interactive nature of Lisp, via a dialog interface, here a REPL. Lisp uses late binding, which makes it possible to update function definitions in interpreted and compiled software.
The base for interactive Lisp development is:
* a procedure to read data
* a procedure to evaluate data as code: EVAL
* printing
* a Read / Eval / Print loop
* additionally Lisp provides an incremental compiler and a file compiler
* LOAD to load code
Still a typical Common Lisp application or library consists of files. ASDF is the moral equivalent of "make" and runs the file compiler. Quicklisp will transfer Lisp software in the form of files to your local machine, compile the files there and load them.
So far we have not used "images". If you check the ANSI Common Lisp standard, there is not a single word about "images" in the standard definition.
When there are some and well-known, yes. Start to develop macros where you do not know how arguments are evaluated or when, half of which you do not know and good luck figuring out how to use and combine things with functions/macros in other places.
They are totally double-edged and in many occasions more trouble than people would admit bc they fall in love with them and how terse they can look. However, scaling this without additional walls and freely is, in my experience, very difficult.
I would guess a team would be so clever to develop maintainable macros.
In many places it's actually the very idea not to know how the thing is evaluated. One writes more descriptive software and does not specify execution details.
You can write unmaintainable software in many ways. Macros are a tool for code generation. How to write and use them can be learned, just like people learn to maintain large class libraries in Java.
Really, there are many of examples of Lisp code bases which make heavy use of macros and where the code was written by tens to hundreds of people.
For example much of the user facing Lisp functionality itself is macros.
Something like CLOS has much of its functionality exposed to the programmer as macros, which sit on top of functions and OOP. It's a domain specific extension to Common Lisp for OOP.
GUI libraries use macros, tools for 3d modeling use macros, ...
Whenever groups of people use code, macros are a tool to provide common language extensions. Like any tool, it needs to be learned how to use it.
Macros are inherently more complex: they can transform ASTs, they can evaluate in several ways, they can inject variables in the same scope, they caan use the surrounding scope in surprising ways.
Functions have very well-defined input and output marks on it, which gives more structure.
I think you will agree that while macros are more powerful, it is way easier to write code more difficult to maintain and look at than with functions.
> Really, there are many of examples of Lisp code bases which make heavy use of macros and where the code was written by tens to hundreds of people.
I wonder when why people move to "inferior" languages like Python, Java or Go. Because they give you MORE structure, not construction material. The construction material can be used in so many clever ways that it is not even funny.
If there is a reason why people move to less powerful languages for team development that is because in some ways you find it easier.
In theory, Lisp is super powerful. It is true, I do not deny that. But it looks to me like macros are most of the time more trouble than not. With higher order functions and without macro abuse you can have more structure and code that maybe is not as terse or "good" at some point, but clearly readable and without any suprise in scope, hygiene or many things that can go deeply buried.
I would not remove macros from Lisp, though. But their use should be limited. I heard some reports (sorry I do not remember the source) that macros usually end up in DSLs that only the makers understand or that are at least difficult to understand for others. For sure there are ways to mitigate it with better docs and others, but they are still macros.
Yes: well-known, a few and well-documented. Now give that power to literally every programmer and let them use it freely. Then the cognitive overhead is unavoidable, like with anything else. But with macros things can get way more obtuse than with functions and a few pre-made mechanisms in a language that everyone understands.
You should not be disregarding one of the most powerful features of Lisp due to a lack of understanding. Imagine if a Haskell programmer rejected typeclasses because they are initially difficult to write and potentially difficult to grasp.
If you want a taste of the power of Lisp macros, check out "Monad Macros in Common Lisp" by David Sorokin (https://cl-monad-macros.common-lisp.dev/monad-macros.htm).
Not natural actually, but coming from experience in reading and using. You think it is great for using until you have to use the macros from others or other people your macros and there is a somewhat lack of docs, which is a common thing in real life.
I'm curious, when do we actually need that? I've been designing my own PL and one thing I realized early on was that we can either provide high level abstractions to increase the expressiveness of the language for problems that are far away from the machine (e.g., business logic which shouldn't be concerned with how you assign memory in loops), or we can let the users do that on their own.
The second approach is Lispy, but that shifts the responsibility of creating abstractions to users. Users already make mistakes in trivial code; to give them the entire AST is mostly detrimental to them (it's like giving them a bigger gun to shoot themselves in the foot, if that makes sense).
Everyone who reads a for loop in Python quickly groks it. But now imagine presenting it in its AST form... There's a reason much of our code doesn't look like AST—we are not computers; we think in terms of abstractions, concepts, etc. which may be cumbersome to present in AST format.
(loop :for x :below 10
:do (print x))
This is a macro that presents a new abstraction/concept that's not "in AST format". It's a concept that's presented in syntax similar to any of the stock imperative languages.That's the raison d'etre of macro: to expose these concepts/abstractions/etc. in a direct manner.
There are bad macros, to be sure, which are half-baked and underdocumented. That's no different a criticism from Python functions being 500 line god functions with boolean input flags, etc. Both cases are cases of bad code.
Python as an example, iteration is a concept: go over a range of things. Complemented with comprehensions that can transform/filter with regular syntax that is always the same (if, f(x) or whatever).
Comapre it to this: https://lispcookbook.github.io/cl-cookbook/iteration.html
Is that worth the trouble, seriously? For sure it is super powerful (Python looping is quite powerful also). But what is the cognitive overhead of that, with custom syntaxes included?
Built-in, of those above, are mapcar and loop.
Python iteration isn't so much about ranges, I thought. See: https://kinsta.com/blog/iterables-in-python/
"You" can provide those syntax abstractions as macros. "You" can also use them yourself. But they then can be embedded in Lisp, you don't need to provide a new programming language version or even a new language & implementation with those abstractions. The user may be sophisticated enough to provide his/her macro abstractions.
I wish someone invented a statically typed LISP with great ergonomics, tooling, packaging, modularization and mobile+desktop+WASM support.
I also think LISP missed out on data-science and ML - that was one field that LISP vendors had a chance to take the throne, but Python won the game since LISP never bothered to participate.
What you suggest exists, but it's not the reason people turn away from Lisp. Lower hanging fruit exists. "I have to learn Emacs? No thanks." itself is an impassé for a vast majority of people who might be a candidate to try Lisp.
There's a perception on websites like HN and Reddit that Common Lisp is super hard to understand and it's this exclusive thing, but I feel the exact opposite way. I think people think it's this exclusive thing because 1. they never used it 2. their only perception of a Lisp is a Scheme (which is not Lisp, because it's Scheme), which is a bit of an ivory-tower hacker language, to be honest, because it gives you so little to work with (and it's intentionally less flexible, less friendly to use, in the name of simplicity). I think Common Lisp is very much not.
Common Lisp tends to be written in this pretty verbose style (with long, descriptive names for everything, since a name can be anything up to 1024-characters) that utilizes the fact that functions, variables, etc are in different namespaces pretty heavily (so you can freely reuse names of existing things, in a scope, where appropriate), because the point is that the code will be read by humans first and machines last. Reliance on context is thought of as a bad thing by a lot of programmers, but humans are very good at resolving things by context, and Common Lisp's syntactical regularity makes it very trivial to know what things are what.
Macros are difficult to write for a beginner, but there are really only a few rules to keep in mind when writing basic ones (which are most of what many will write). Other people's macros end up being readable, even when you don't quite know what those rules are, because they're written in a descriptive way.
It's common to see people say something along the lines of "Lisp encourages programmers to write their own mutually unintelligible dialects of the language to solve their problems" but I find it pretty easy to read other people's (contemporary) code in Common Lisp. I do find it quite difficult to read Scheme code that comprises of a million nested lambdas all with vague, single-letter variable names, though.
I've no idea what Clojure is like, so maybe that's massively more complicated and that's coloring your perception, but I don't know. I think Common Lisp has pretty good ergonomics as-is (except all the legacy, leftover bloat in the standard, and awkwardness that arises with CLOS not being as well integrated with the rest of the language as it could).
There's no reason to write Scheme code like that. Or in Common Lisp, or any other language with lambdas.
AFAIK Hackernews is still written in Arc.
> "Okay, if Lisp is so powerful as you say it is, then give me one example where Lisp is used? More importantly, give me one example where Lisp was used and didn't get rewritten in another language later?", I hear no concrete example given by the Lispers.
Maybe the problem are statements like that, which sound a bit like trolling, which people are tired of? There is more than one example of software written in Lisp and still maintained in Lisp.
The heavy line noise in service of an easy to understand macro system just isn't worth it (moreover, a lot of languages have advanced macros these days without S-expressions).
Looking back, I think I was so into Lisp because I just wanted to feel superior and better than the dirty Java or Python programmers?
Just curious: what macro system were you using with Racket? There are, like, 3 big ways to build macros in Racket:
1. Macros by example with `syntax-rules`. This was taken from Scheme and is the original hygienic-by-construction system. Limited in power though.
2. `syntax-case`, which gives you full procedural macros but is a little unwieldy at times.
3. `syntax-parse`, the glorious, most powerful macro system of the three.
I know, it’s confusing.
tbh, Paul Graham's articles on Lisp have done more harm than good to programmers. Calling Lisp a "secret weapon" that supercharges your startup and gives you immense competitive advantage is unrealistic and lacks concrete evidence.
Since then, the landscape has changed.
With great power comes great responsibility, and most people don't want that responsibility.
Lisp has a higher barrier to entry compared to Python or Rust or other languages available. For that simple reason alone, it's not used. None of these imagined reasons about the theoretical power or anti-power of macros, or being a wizard, or whatever are part of the calculus of choosing a language.
Who has time for that these days, except for the very determined and dedicated?
I think Lisp is a superlative language with excellent tools—once learned. But it hasn't had its UI revolution from anybody who cares enough to do the work.
And the reason it is called "style" is that it is not essential to actually getting things done.
I likewise have written Common Lisp for decades. But I also get paid to do it, manage a team that does it, and see immense value in doing these extra things that hackers don't much care for, such as:
- making Lisp compatible with other languages through ABIs
- developing stylistic guidelines
- developing systems for static typing in Lisp to assist long-term development and maintenance of Lisp code
- etc.
So does style or the lack of any of the aforementioned bullets "block" the ability to "get things done"? Strictly speaking, no, but it inhibits outside interest in your project.
I concede that point. Also, I'm the only user of most or all of the Lisp I've written over the last 40 years.
My guess is that it has more to do with the fact that CONS takes a whole list as an argument, then returns a different whole list, which superficially seems too computationally expensive to do in a loop.
That's not what I meant. What Lisp with s-expressions already makes more difficult is that the data syntax is used to express programs.
(defun foo (list1 list2)
(quote (defun foo (list1 list2) (list list1 list2))))
-> A symbol can be an identifier and just a piece of data.Above, the first DEFUN is a standard identifier of the programming language Common Lisp. The second DEFUN is just a symbol.
The first DEFUN form is a program. The second DEFUN expression is just data. Thus it makes no sense to indent the second DEFUN expression like a program. We don't know if it is a program, it could be just anything.
-> A list can be data and a program.
This specific double nature of built-in data structures, here symbols and lists, is already a hurdle to get over.
The developer has to know which lists are data lists, which are forms and which are expressions in inside a form.
(cond ((quote (a))))
-> (cond ((quote (a)))) is a form, which is meant to be evaluated
(a) is data
((quote (a))) is a clause of COND, which is neither data, nor a form to be evaluated
Thus the user has to understand that in Lisp these lists serve different purposes. Which is which depends on the context and the Lisp syntax & evaluation rules.This then even may make functions possible which contain their own definition as data:
CL-USER 9 > #1=(defun foo (list1 list2)
(quote #1#))
FOO
CL-USER 10 > (foo '(1) '(2))
#1=(DEFUN FOO (LIST1 LIST2) (QUOTE #1#))When did that happen?
> "Hacker News was built in Arc, which is a Lisp"
and the follow-on is:
> HN is such a simple website by all metrics, and the fact that CL/Arc was dropped in favor of another language further confirms my belief that Lisp's days in industry are almost over.
He gets the right language for HN (Arc, still the language of the site), and not the Reddit language (CL as you point out, which was dropped for Python, and Arc was never used).
I'm uninclined to make any effort to convince you otherwise until you provide even a hint of a reason why I, or anyone else, should believe you have any willingness whatsoever to allow yourself to be convinced.
I also didn't get the impression that the parent comment was being unreasonable or resentful. Lisp is often portrayed as being special and a secret weapon. It's reasonable to question that given how little it ends up being used in comparison.
Emacs is an amazing piece of software and its heyday lisp was revolutionary. These days though I don’t see what it offers over other general purpose languages.
But that's a software made in Lisp for Lisp. The fact that it also works for other purposes doesn't change the fact that it's a "technology for the sake of technology" product, not "technology for the sake of goals".
maybe you didn't look enough, even on hn, let alone outside it. because, as just one example,
https://en.m.wikipedia.org/wiki/ITA_Software
has been mentioned, maybe multiple times before, here on HN, in reply to questions such as yours.
(it was sold to Google for 700 million a few years later, according to the above page.)
another example is by the founder of the very site that we are talking on: hn. it was founded by PG, who also co-founded Viaweb. See
https://paulgraham.com/avg.html
which is another article that has been mentioned many times here on hn.
Viaweb was later bought by Yahoo for 40 million, iirc, and became Yahoo Stores / Shopping.
such questions as yours have come up many times before in the past on hn.
so it looks like you might not have read them. you could have used the search function at the bottom of the main hn page.
>More importantly, give me one example where Lisp was used and didn't get rewritten in another language later?", I hear no concrete example given by the Lispers.
how is this point more important? it may be, but explain why. and again, did you search enough, before asking?
(and the argument here is about the power of the language, not about the business issues (like hiring) surrounding it.)
I don't think it has to be more important.
an app getting rewritten in another language could be (and often is) due to non-technical reasons, such as management not understanding the power of lisp, or relative shortage of lisp programmers. the same kind of things happen with clojure, ocaml, etc.