So what does Lisp make harder to implement than today's programming languages?
It seems like large-scale composition relies on a well-structured way to define and enforce APIs, and oh wow, typing facilities.
Performance has historically been an issue for Lisp because its model is tightly tied to interpretation, but perhaps modern JIT-style compilation can address this.
Others?
What type of issues do large Lisp projects typically run into?
Common Lisp has long been a compiled language. Its performance is quite competitive when set against Fortran and C. The idea that it's interpreted (and consequently slow) is a very old myth.
Of course, it helps to use the right data structures if you want fast Lisp code (using lists for everything is not the right choice).
> Its performance is quite competitive when set against Fortran and C.
No, not at all. It is the same level as Java, a bit slower but I guess that is because there is more work done on Java. Just because you compile a language doesn't mean it is as fast as other compiled languages. You can compile python down to a binary but it will still be super slow.
If you read the discussions to end, you will notice many objections to the benchmark that you have posted here. Even I have objections. -O3 is not the end of all possible optimizations in C and Fortran.
I hear you, but I was lazy and only gave one reference. There have been, over the years, many demostrations of optimized SBCL being on the same order as C.
Yes, I'm aware (see my nearby comment for more detail).
I very much enjoy writing Common Lisp, but use SBCL almost exclusively specifically because of the amount of (static) type checking it does. Even then, there are significant limitations that often leave me frustrated in comparison.
Hell, to go even further you can implement your own type system on top of Racket's macro system; or better yet, use a macro DSL specifically created for type systems to implement your type system. [1]
It is heavily typed. Very strongly typed for the most part (except numbers). So typed that it won't accept a "character vector" in the place of a string.
But type checking is mostly at runtime, not at compile-time.
The good part is that you can edit your program at runtime and restart it at the exact point the error happened, very easily.
In context, particularly given the reference I made to Typed Racket, it should be abundantly clear that I'm referring to the lack of static typing there.
That being said, I think you'll find truly untyped languages hard to come by. Other than assembly, Forth (similar to assembly in many ways), and esolangs such as Befunge (also quite similar to assembly), languages that see widespread use always check types eventually. Checking types eventually is table stakes. Checking types at compile time, before what you wrote has a chance to explode on you in an unpredictable manner when that one branch for an edge case finally gets taken after a few days of uptime, that's the truly desirable feature that not all languages manage to provide.
It seems like large-scale composition relies on a well-structured way to define and enforce APIs, and oh wow, typing facilities.
Performance has historically been an issue for Lisp because its model is tightly tied to interpretation, but perhaps modern JIT-style compilation can address this.
Others?
What type of issues do large Lisp projects typically run into?