C was designed on a PDP-11, a computer much more powerful than the mainframes where Lisp was already running since 10 years, so Lisp implementations were already quite good for most tasks by then.
While C designers were trying to create UNIX at AT&T, Xerox PARC was busy creating Smalltalk, Interlisp-D and Mesa/Cedar.
Other companies were creating Genera and the Connection Machine,
In the end Worse is Better won, because the machines were too expensive for most pockets, normal developers could not grasp Lisp, mismanagement from those companies and UNIX was kind of cheap when comparing prices, with source code available almost for free (AT&T was prevented from selling it early on).
And these figures aren't using the SBCL Lisp compiler which should currently be faster than the one cited.
You are correct, it wasn't designed to compete against C. And it has a garbage collector. But make the right choices and a compiler like SBCL can produce surprisingly "clean" (optimized) machine language code.
Common Lisp has some very fast implementations (I think SBCL is the fastest) and it was designed to be a systems language. It can be optimized to be as fast as C.
Sorry if dumb question but how is this possible when it's garbage collected?
Now I really feel like I need to learn a Lisp though.. Is there a certain Lisp you would recommend that's practical enough I'd use it for projects? Racket?
Just check the hardware capabilities of systems having Lisp 1.5 support, several years before C was created.
Lisp is not only manipulating lists, it grew up to natively support all relevant data structures, including primitives to handle systems programming tasks.
Regarding GC and systems programming, there are plenty of GC enabled systems programming languages, the main point is that they offer features to control the GC and also do stack and GC free allocation if required.
Some examples would be Mesa/Cedar, Modula-2+, Modula-3, Oberon, Oberon-2, Oberon-07, Active Oberon, Component Pascal, Sing#, System C#, D
> Sorry if dumb question but how is this possible when it's garbage collected?
On a big or complex system you end up at least doing one or both or two things:
a. Having to manage many temporal (transient) objects in memory. Thus you end up doing some sort of garbage collector, either doing it yourself, or using the facilities provided by the languages, or a library.
b. Allocating fixed big blocks of memory (such as arrays, or doing a "malloc") and then using this block of memory as your storage area, which then you manage.
Usually on C programming you do (b), although you can also do (a), it is not so easy.
Usually on Common Lisp programming you do (a) very easily, but you can also do (b) by allocating an array and a bit more stuff. It is not difficult, really.
> how is this possible when it's garbage collected?
Common Lisp lets you give "hints" to the garbage collector, so you end up with pretty much what you'd have in C but without the manual memory management.
> Is there a certain Lisp you would recommend that's practical enough I'd use it for projects?
Racket is very nice and comes with great documentation, a huge standard library and a very handy IDE. Clojure was hyped a lot so it has lots of libraries, which however might be of dubious quality or unmaintained by now, and it's on the JVM, which might or might not be a good thing for you. Common Lisp is very versatile and "pragmatic", but lacking in external libraries.
While C designers were trying to create UNIX at AT&T, Xerox PARC was busy creating Smalltalk, Interlisp-D and Mesa/Cedar.
Other companies were creating Genera and the Connection Machine,
In the end Worse is Better won, because the machines were too expensive for most pockets, normal developers could not grasp Lisp, mismanagement from those companies and UNIX was kind of cheap when comparing prices, with source code available almost for free (AT&T was prevented from selling it early on).