Here is the source code for the same minimax rational approximations fitting in Lisp. Why not? This particular routine is not especially vector oriented anyway, and having prototyped the routines in NML we can now do an even nicer job in Lisp.
Nicer? Well, at least in the sense of a slightly more sophisticated handling of exception trapping using the Condition system of Common Lisp.
I like Lisp. The only thing that really bugs me at times is the fact that it isn’t tail-pure by default. I suppose that is because tail-pure code creates difficulties for runtime debugging and tracing, neither of which I do very often. Lisp without tail-optimization often forces a programming style that is distinctly 2nd generation -- i.e., non-functional in style.
NML is tail-pure at all times, because OCaml produces tail-pure code. All function calls in leaf positions of the m-Trees are turned into direct jumps. As a result, a tail-recursive routine in NML can run forever without blowing the stack. Not true by default in Lisp. In Lisp you have to explicitly ask for it to produce tail-pure code by the non-portable and obscure means of
(declare (optimize (debug 1)))
or some such declaration.
Doing CPS coding in Lisp requires careful specification of tail-pure sections of code. And it generally requires compiled code, not interpreted. Otherwise you will blow the stack.
With NML and Scheme, CPS continuations never cause any stack damage. You can go all day long with that style if you like.
The other big difference between NML and Lisp is that Lisp has separate notions of function and value namespaces. NML is more like Scheme in that a binding can only refer to one item. A symbol in Lisp can be bound to both a function and a value. Furthermore, bindings in Lisp are mutable -- they can be changed at will. Not so in NML.
So in some respects, Lisp shows its second generation heritage. It is still a great language. Lisp is the language of computer research. It is the grandfather of ML and Prolog. You can do anything in Lisp if you are clever enough.
NML is my scratchpad language. I turn to NML first, whenever I have a numerical problem to solve, but I would be very hesitant to deliver production code in NML. I would hesitate less with well tested Lisp code, but I would still worry about what never got tested. For absolutely bullet-proof production code, I would have to recommend OCaml.