Lisp is quite good for that, really. Numerical computation, parallelism, etc. With a good compiler, using unboxed values and primitive arithmetic and Boolean operations on ints, most code will compile to not much slower than the C version.
For example, I just saw an old paper [1] where the author implements dynamic compilation from Lisp, to Lisp, in Lisp, for parsers. One describes the language to be parsed, in a high and abstract level in a DSL in Lisp. The Lisp program then compiles that definition into to a low-level sequence of unboxed boolean and arithmetic ops and conditionals in Lisp which, being primitives with direct machine code equivalents, the Lisp compiler can translate into reasonable machine code. The end result was probably only a few times slower than doing the recognizers directly in C.
Not so different from the usual parser generator technique. But the nice part of doing it that way is that you retain the full Lisp system; your generated blobs of "machine-level Lisp" are still just another Lisp object, so you can take your generated functions and single-step it in interpretation, or transform it further. I suspect that's a big part of why Lisp was so popular for so long. Other languages provide similar capabilities now, though sometimes not so general in ability. But for a long time, this sort of meta-programming where you write the program at the high level to generate the code at the low level for you, was basically a proprietary superpower for Lisp.
For example, I just saw an old paper [1] where the author implements dynamic compilation from Lisp, to Lisp, in Lisp, for parsers. One describes the language to be parsed, in a high and abstract level in a DSL in Lisp. The Lisp program then compiles that definition into to a low-level sequence of unboxed boolean and arithmetic ops and conditionals in Lisp which, being primitives with direct machine code equivalents, the Lisp compiler can translate into reasonable machine code. The end result was probably only a few times slower than doing the recognizers directly in C.
Not so different from the usual parser generator technique. But the nice part of doing it that way is that you retain the full Lisp system; your generated blobs of "machine-level Lisp" are still just another Lisp object, so you can take your generated functions and single-step it in interpretation, or transform it further. I suspect that's a big part of why Lisp was so popular for so long. Other languages provide similar capabilities now, though sometimes not so general in ability. But for a long time, this sort of meta-programming where you write the program at the high level to generate the code at the low level for you, was basically a proprietary superpower for Lisp.
[1] https://www.plover.com/~mjd/misc/hbaker-archive/Prag-Parse.h...