For a start, it’s worth reading Xaviery Leroy’s master’s thesis: https://xavierleroy.org/publi/ZINC.pdf
I have a distinct memory (which might be false, b/c it was >30yr ago) of reading it and getting the message:
“I’ve told you this long and complicated theoretical story, but really, I just wanted to make it run like C as much as I could”
At the time (1992), there was an ML called SML/NJ that was … well, it was a massive memory hog, b/c it chose to do the mathematically correct thing a few too many times. Like, left-to-right call-by-value evaluation. Heap-allocated closures like crazy. You had to run it on the biggest desktops you had. Caml-light came along, and because of -judicious- implementation choices (which were reflected in the semantics you had to know to reason about your programs), it could run on … basically anything in the office.
At INRIA in 1992 in Batiment 11 there were two color Sparc-10 machines (on the desks of the group leaders). They were basically the only machines on which SML/NJ ran well. Whereas, caml-light ran on every machine in the lab, including old SUN-2 machines (68010, yeah baby!), Sony NeWS stations, and on and on. Sure, caml-light was a bit slower. But it fit in constrained memory, and that was a big, big deal. Coq in caml-light ran on every one of those machines. Coq … ported to SML/NJ (I did the port, only to realize the error of my ways) could only run on those two Sparc-10s, b/c on any other machine, it spent all its time paging, paging, paging.
With the passage of time OCaml came along, with a native-code compiler, etc, but the initial … “attitude” of caml-light, that it was designed to fit the hardware of the day, was critical to its success. And you can see it in the world: SML/NJ … where is it? I haven’t seen it running in the wold in decades.
As an aside, I’d note that one of the seminal grandfather languages of computer science, ALGOL-60, was call-by-name. It was theoretically lovely, but … well, there’s a reason that the languages that achieved real longevity are all call-by-value languages (and Haskell simulates call-by-value with its monads).
Theoretical beauty and five bucks’ll get you a double-espresso at Peet’s. But if you want to get stuff done, you’re going to have to make compromises.
ETA: BTW, caml-light’s officially-unspecified, but in practice right-to-left evaluation order, had real consequences. Coq (for instance) had several places where code either didn’t work, or was inexplicably exponential-time, when ported to caml-light from “Caml Heavy” (the old Caml that ran on LeLisp). Problems like that came up from time-to time when people were porting code, or when they were writing code naively assuming (as I did, as everybody did) that evaluation was left-to-right. So these low-level choices for the sake of tractable implementation were reflected in every level of reasoning about the programs we wrote and ran on caml-light.