I'm not denigrating Lisp. I'm saying the network effects favored C because the PC happened to take off.
I'm not denigrating Lisp. I'm saying the network effects favored C because the PC happened to take off.
And why wasn't it ported to the ones that mattered? I keep hearing about how easy it is to build a (simple) Lisp compiler. Why wasn't it ported, or a fresh one built?
> The existing code was irrelevant and not portable.
Why was the existing code irrelevant? In ten years, nobody wrote anything in Lisp that mattered to anyone?
In fact, there were Lisp compilers for the PDP-10, which (I presume) could run on the PDP-11, where C began to take over the world. Why didn't those Lisps take over the world? You can't explain it just by C existing on the right machines at the right time. (There wouldn't have been C on the PC if it hadn't taken off - at least to some degree - on the PDP-11 a decade earlier.)
I don't think awareness of Lisp was evenly distributed among people developing on PCs in the time period when the network advantage was obtained. Even if it was, if there were already a decent C compiler, I don't think most practical engineers would immediately embark on a compiler development project. During this era, those who did know about Lisp certainly would have regarded it as being too resource-intensive for work in a resource-constrained environment like the PC.
I think it's specious to say it's easy to develop a simple Lisp compiler, so why didn't anything get ported. The code you may have wanted to port would not have been written in some minimalist dialect of Lisp, it would have been written in ZetaLisp. So there would be assumptions about resources and the underlying system that you would have to fake. And again, we're talking about porting from a resource-rich environment to a resource-scarce environment.
It was probably a reach for me to say there wasn't anything to port. But what would someone have wanted to port? A graphical application that ran on a Lisp machine would have made assumptions about the display that aren't true about a PC. An academic AI program would have been too short on resources to be much use.
What wound up selling the PCs in the early days was business applications. Were there an assortment of useful business applications on Lisp machines that there was commercial demand for? WordStar and Visicalc invented that territory and were first released in the late 70s—does anyone remember programs for the Lisp machine that businesses were clamoring for? And really, software churn has always meant there are more new programs in use than old ones.
What I don't have an explanation for is why the C compilers produced better code than the Pascal compilers. Partly, I know p-code made it faster to build a Pascal compiler but I don't know why it inhibited development of more performant ones. Turbo Pascal's speed of compilation was a result of not having an AST, which probably inhibited performance optimizations, but that may have been too late in the story to explain anything. And I don't have an explanation for why nobody developed a Lisp-like language that had explicit allocation. My best guess would be simply that their attention was elsewhere, probably working on AI, which wouldn't bottom out until after the winners were already entrenched.
By the way, in case it isn't clear, I am really enjoying this conversation. I'm very interested in this window of time in computing and if I have a wrong idea about something, I do want to know. The only way to preserve this history is to talk about it and keep the memory alive.
My assertion is that you're looking at the wrong decade for C's network effects. You should be looking at the PDP-11 decade, not the PC decade. And in the PDP-11 decade, I believe there was much wider awareness of Lisp. (I was a kid then, so that's just my impression. I don't actually know.)
> It was probably a reach for me to say there wasn't anything to port. But what would someone have wanted to port? A graphical application that ran on a Lisp machine would have made assumptions about the display that aren't true about a PC. An academic AI program would have been too short on resources to be much use.
Fair point.
> And I don't have an explanation for why nobody developed a Lisp-like language that had explicit allocation.
Lisp allocates all the time. You have to work hard if you want it not to. So if you want explicit allocation, you'd have to invoke it all the time, and it would really get in the way - far more than it does in C. (Far more things are allocated in Lisp than in C.)
But you could mean "why didn't someone make a Lisp where you could explicitly allocate a block of memory if you chose to"? You wouldn't have to always use it in that case, so my objection in the previous paragraph doesn't apply. But if you did that, first, the garbage collector would have to know how to clean up those objects (or else you'd have to explicitly free them), and second, you'd have to be able to do something with it. Lisp, to my (very limited) knowledge, doesn't have a way to treat an allocated block of memory as anything other than a cons pair. You'd have to add that to the language. You could do it, but it would be something tacked on to the side of the language, not something you could use the same as the rest of the language.
This is the crux of it I think, and unfortunately my flashlight isn't bright enough to get much further. I was born in 1981, so this is all reconstruction for me. Unfortunately, the people who were there are getting scarce. Anyway, thanks for talking it through with me!
I was not around but from the literature it seems Lisp trolls existed even back then - for example Ted Nelson's Computer Lib / Dream Machines contains some very negative and very mistaken statements about Lisp, and it was published in 1974.
> Lisp allocates all the time. You have to work hard if you want it not to. So if you want explicit allocation, you'd have to invoke it all the time, and it would really get in the way - far more than it does in C. (Far more things are allocated in Lisp than in C... Lisp, to my (very limited) knowledge, doesn't have a way to treat an allocated block of memory as anything other than a cons pair.
Between this comment and your ignorance of the difference between a PDP-10 and a PDP-11 I get the impression that you do not know anything about computer history or about Lisp or about what constitutes memory allocation. Please stop trolling.
Recently while reading, Appel's Compiling with Continuations, I read some mistaken claims about Lisp and scope, one doesn't have to be a troll, which requires intent, to make ignorant claims about Lisp, parsing or any subject. Although the amount of ridiculous arguments from people who clearly haven't used it (or at most used it very briefly) does make one's blood boil at times.
Here is another one I found looking for the quote I was remembering.
> "It has higher-order functions, meaning that a function can be passed as an argument and return as the result of another function – as in Scheme, C and Haskell, but not Pascal and Lisp.
Thank you for your charitable assumptions. You might be even more charitable and state what's wrong with what I said.
My understanding is, 1, that every newly-created cons pair requires an allocation, 2, that every new list entry is a new cons pair, and 3, that you can avoid creating them but you have to keep a very careful eye on your code in order to do so - the normal way of writing code will cons frequently.
Which, of those statements, do you consider to be wrong, and why?
Every one of them. You do not understand the difference between what the program code does and what the programming language implementation does, and your underlying assumption is that there is a difference in how a Lisp runtime without garbage collection would manage memory allocation and how the C standard library manages memory allocation.
I am going to assume you need a stdlib.h refresher:
void *malloc(size_t size);
void free(void *ptr);
How do you think free works? How would you write a linked list implementation in C?I just happened to have done some software archaeology on a Lisp implementation without a garbage collector a while ago (https://github.com/vsedach/Thinlisp-1.1), and the memory allocation and lifetime management is exactly the same there as in C++ - manual management and dynamic extent regions (RAII).
Now I really want to get pedantic with each of your points, because individually each is wrong in interesting ways:
> 1, that every newly-created cons pair requires an allocation
This statement is a redundant tautology ("every new allocation requires an allocation"), but even the correctly phrased assertion that "CONS always allocates" is not always true:
https://en.wikipedia.org/wiki/Hash_consing
http://3e8.org/pub/scheme/doc/lisp-pointers/v1i3/p17-white.p...
> 2, that every new list entry is a new cons pair
Again, redundant, and again, not always true, because of hash consing and CDR coding:
https://en.wikipedia.org/wiki/CDR_coding
> 3, that you can avoid creating them but you have to keep a very careful eye on your code in order to do so - the normal way of writing code will cons frequently.
If you do not need to allocate lists, do not allocate lists. There is no "normal" way of writing code that exists outside of what your performance requirements are, what the language semantics are, and what the language implementation provides in terms of those semantics. The only situation where you cannot avoid frequent allocations is when all the data structures are immutable.
> You do not understand the difference between what the program code does and what the programming language implementation does
False.
> I am going to assume you need a stdlib.h refresher
False, and even if I did, that wasn't much of one.
> How do you think free works?
I've seen an implementation.
> How would you write a linked list implementation in C?
I've had the pleasure (?) of doing so.
On to the meat of your reply: I was not aware of any non-garbage-collected Lisps. Still, isn't it fair to say that such Lisps are by far the exception?
I was under the impression that immutable was the normal way to write Lisp. ("Normal" here not meaning "the one right way" or "the way the language tries to make you write" - Lisp doesn't do that - but more "the way the majority of people write it".)
And even if you're going to not write it that way, if you really want to avoid allocations, don't you have to also be careful what library functions you call, since many of them cons?
The evidence is that you insist on posting a bunch of "I was under the impression" bullshit instead of spending a few minutes using a search engine. That is what is really annoying. Why do you think that your basic thesis that programs written under the assumption that there is garbage collection will not work well when there is no garbage collection is a novel or insightful contribution to the discussion about the original post?
AnimalMuppet is basically right. Normal, everyday Lisp code does quite casually allocate memory: more or less of it depending on circumstances.
Implicit dynamic memory allocation occurs in places where in the analogous circumstances in C it wouldn't occur.
The abstract semantics of Lisp (such as ANSI CL) call for dynamic allocation of all lexical variable bindings, because in the abstract semantics, these have indefinite extent.
Each time a lexical scope with variables is entered, dynamic allocation takes place to create the fresh bindings, which enables continued access to these bindings after that scope's evaluation terminates.
Such allocation is only avoided as a matter of optimization: the Lisp compiler analyzes the scope to determine that no escaping closures are created in it and then the bindings can be allocated stackwise (dynamic extent) similarly to C's automatic storage.
Nothing in ANSI CL guarantees to you that (let (x)) will not allocate a piece of memory for x which endures after the form terminates, and has to be reclaimed.
I was not aware of this, but I can think of one reason: Pascal does bound checks on array references.
Having lived through the Pascal-to-C transition in academia, I was under the impression that the main reason for C's success was that it came with Unix, and Unix was free (at least to schools at the time), while other languages and OSes cost money.
On MS-DOS, Turbo Pascal and Turbo C had equal code quality and for the use cases where bound checking or integer overflow checking could be a performance issue, it was possible to disable it.
In both cases you would end up using Assembly anyway, because on those days compilers were pretty bad generating code.
Long answer is a bit more complex.
UNIX was the only OS where C was relevant, and AT&T was forbidden to sell it, so they made the source code available to universities and companies for a nominal price.
That was already a big difference, instead of paying a sum of several thousands for closed source OS stuck to a specific mainframe, companies and universities could get something with source code for about $70 (if I remember correctly).
Thus UNIX eventually became the foundation of 80's startups like Sun and SGI.
Home computers firmware was basically Assembly, where C (actually K&R C dialects) was yet another language among all the available ones.
When the 16 bit revolution happened, there were several 16 bit computers systems done in a mix of Pascal and Assembly. The most notable ones Apple Lisa, Mac OS, MicroEngine and Corvus Concept.
http://basalgangster.macgui.com/RetroMacComputing/The_Long_V...
http://basalgangster.macgui.com/RetroMacComputing/The_Long_V...
https://en.wikipedia.org/wiki/Pascal_MicroEngine
https://en.wikipedia.org/wiki/Corvus_Systems
As a notable example, Photoshop started as an Object Pascal application, which was later on ported to C++.
http://basalgangster.macgui.com/RetroMacComputing/The_Long_V...
So you had UNIX variants gaining a foothold on university campus and companies, with people wanting to write applications on their tiny (cheaper) computers at home, which like JavaScript and the Browser nowadays, C eventually escaped UNIX.
Apple eventually gave in to market pressure and rewrote their Object Pascal based SDK into C++ and C. And even tried their first stint at UNIX with A/UX.
http://basalgangster.macgui.com/RetroMacComputing/The_Long_V...
Corvus Systems tried to pivot their computers into Concept Unix workstation.
The Amiga OS was written in a mix of Assembly and BCPL, and eventually got its UNIX port.
https://en.wikipedia.org/wiki/Amiga_Unix
C by virtue of being UNIX's system language meant that its tooling was free with the OS, while any other programming language had to be bough separately and still you would need to write FFI to C at some level.
As side note, eventually C compilers stopped being available for free when Sun started the trend of selling the SDK, which made the largely ignored gcc to start getting contributions.
While this was happening, Brian Kernighan decided to push for C, with articles like
"Why Pascal is Not My Favorite Programming Language"
http://www.lysator.liu.se/c/bwk-on-pascal.html
Which ignored the fact that the majority of Pascal dialects had features that covered his complaints, specially the second ISO revision, Extended Pascal. And that outside of UNIX most C compilers were actually dialects, which is one of the causes for UB.
There were other bash articles flying around like "Real Programmers Don't Use PASCAL".
http://www.ee.ryerson.ca/~elf/hack/realmen.html
On the PC world, OS/2 and Windows were being written in C, but the majority of application developers were actually already jumping with C++ wit C Set++ for OS/2, OWL, VCL and MFC on Windows.
Another nascent PC OS, BeOS, was also being written in C++.
It was the rise of FOSS UNIX software, with C as its systems language, that shifted the balance towards C. To stress it again, just like JavaScript on the browser.
If you look at the history of systems programming languages, the ones that lasted longer were always the ones that were the way to write software for a specific OS.
Regarding Pascal, the majority of vendors started to consider Turbo Pascal as the pseudo-official standard, which when Borland decided to ignore small developers and focus on the enterprise, just kind of killed the Pascal market. Specially since Turbo Pascal was only focused on PC.
There is probably a bit more to rant about, but I guess you get the idea.
I think blaming either of those articles is mistaken.
Politics and Unix would explain it if, people were borrowing and/or aping Unix in their OSes, or if people just generally had the impression that C was more powerful. Is that kind of the direction you're pointing?
Anything else required being loaded from tape or floppy, including running CP/M instead of the ROM firmware.
Remarkable systems in these days Spectrum, C64, Tandy, Atari, MSX, Apple.
You can find a few programming books here:
http://www.worldofspectrum.org/documentation.html
Then we moved into 16 bit, the major platforms being MS-DOS, Lisa and MacOS, Atari and Amiga.
MS-DOS was coded in Assembly, Lisa and MacOS in Object Pascal, Atari and Amiga used a mix of Assembly and BCPL.
MS-DOS and AmigaOS had quite a few UNIX influences on them.
Regarding my experience in Portugal, MS-DOS applications were being mostly programmed in Assembly, Pascal, C, C++, Basic and Clipper. Then there were some outliers using Prolog, Modula-2, Forth.
Microsoft and Borland were the two biggest vendors on the market and supported almost the same set of languages, with Borland ones being more programmer friendly.
Amiga were usually programmed in Assembly, Basic, AMOS, Modula-2 and C.
Mac OS was using Object Pascal until by System 7 release they decided to switch to C++.
UNIX started to be quite relevant by the mid-90's, and many wanted to continue the work on their home computers, that were doing at work or university on the expensive computer centres running some form of UNIX.
For example, I wrote K&R C code on MS-DOS for OS classes where the teacher would bring a PC tower into the class running Xenix, where each group would get a turn trying to execute their UNIX assignments.
Think a bit like how the Web influenced the desire to have JavaScript everywhere with node, it was a similar experience.
UNIX was being adopted by companies, the other contender being VMS (using BLISS as systems language).
With C companies had an ANSI/ISO standard ratified in 1989, while with Pascal, there was a de facto standard Turbo Pascal/Object Pascal with ISO being largely ignored, but they were confined to MS-DOS/Mac OS.
As I mentioned above, this raises questions about why C came to dominate Pascal. They both had a comparable early foothold on PCs.
The PDP-11 was in no way compatible with the PDP-10, and there was no way a PDP-10 Lisp implementation like Maclisp or Interlisp would fit on a PDP-11. All you have to do is Google "PDP-11 Lisp" to see that there were many different Lisp interpreters and at least one compiler implemented for the PDP-11 throughout the 1970s. Likewise Intel processors - the first implementation of Lisp on the 8080 was done by Takashi Chikayama (http://www.logos.ic.i.u-tokyo.ac.jp/~chik/) in 1976 (http://www.softwarepreservation.org/projects/LISP/utilisp/ut...)