Lisp satisfies 1, 3 and 4 I’m pretty sure, and maybe 2 depending on your definition of small. Idk about 1 though.
> Ability to use static dispatch, static field offsets and stack allocation.
> Control over memory layout - at minimum being able to express arrays-of-structs without pointer soup.
---
So reading between the lines a bit, I believe the author is asking for an REPL'd, interpreted, and fast running Go, Swift, Rust, C++, or Zig. (which to me is an interesting problem -- I basically use shell as my REPL for C++)
OCaml with new value types would qualify, and Java with value types would qualify, but they're not there yet AFAIK.
I think Julia/Clasp can get that kind of performance in some cases, but it's not predictable performance, with language control.
(copy of lobste.rs comment)
That's why the interactive versions of languages like C, Rust, Haskell typically are not very interactive and come with a lot of compromises. Often compromises at the boundary of compiled and 'interpreted' code.
What does 'interpreted' mean and why would we actually need it? Lisp as its bases has a radical interpreter: it interprets source code in the form of s-expressions. Most people think of interpreted code "byte code interpreters" - that's an entirely different form. The source code gets compiled to a byte code interpreter. In Lisp its quite often that one uses incremental native code compilers. These achieve much faster running code, in a spectrum of possible optimizations: optional type declarations, reduced runtime safety, code inlining, stack allocation, type specialized code generation and more. Many of these optimizations make the code harder to write. SBCL by default always uses the native code compiler. If we want "byte code" interpreted code, there is no way to make it fast without either some form of native code compilation (typically a JIT compiler) or writing the code in some other language (Python + C). The alternative is to get rid of byte code and having a native code compiler, with the drawbacks: one or more hardware architectures to support.
> Control over memory layout - at minimum being able to express arrays-of-structs without pointer soup.
That's a problem. Lisp needs to deal with it when interfacing 'foreign' memory. Thus it typically has a foreign-function interface.
> I believe the author is asking for an REPL'd, interpreted, and fast running Go, Swift, Rust, C++, or Zig. (which to me is an interesting problem -- I basically use shell as my REPL for C++)
There are compromises to make. "Interpreted" already is vague, see above. "Fast running" - is it always "fast running"? Is that possible? While being "interactive" / "interpreted"?
"REPL" is another concept with a range of possible meanings. Is a Read Eval Print Loop like in Lisp integrated into the language (read, print, eval, loop are primitives in the language) and is it the base for interactive programming. Is it a glorified command line interpreter which basically can call functions on data?
// layout.h
struct MyRecord { ... }
#define N 1024*1024
MyRecord myarray[N];
And then suppose you have 1000 translation units that #include layout.hSo whenever you change N, you have to recompile a lot of code.
And then you want to compile myprog quickly, and run the following quickly:
cat 2gigs.txt | ./myprog
It's an interesting problem, but I think from the perspective of an interactive language, it does make sense to have some kind of fast mode and slow mode ... the classic debug/release build split is precisely that. I would settle for an interactive C++/Rust, with a good incremental build system, where you can choose the build variant!C++ build systems suck, and Rust often has to interface with them. And both C++ and Rust are not designed for fast interactive use. They have a lot of syntax that allows the control over memory, and that's perhaps a bigger problem.
I also don't really like typing code into a REPL -- I use an editor and a shell (and Ninja, which turns out to be crucial for fast C++ dev).