I find the `ref` syntax of SML much nicer to use than the mutable record syntax in Ocaml.
SML doesn't have all the dotted math operators for floats.
SML strings are immutable which lends itself to a lot of potential optimizations (and there's always byte arrays if you actually need to mutate).
Ocaml let vs let expressions are annoying to me.
SML has a standard. "The implementation is the spec" in my observation always leads to problems.
My wishlist for SML:
FIX USE COMPATIBILITY. It's intentionally not specified by the standard. This makes portable code very hard. I'd love to see an approach more like JS, but without dynamic imports (useless) and with support for something like GO_PATH plus maybe the ability to recognize and import from URLs (especially .git and .sml).
JS style template strings with interpolation (the type system is at least smart enough to convert primitives to strings) and multi-line capabilities. This would also be an easy backward-compatible way to add support for unicode. Guarantee the ability to implement them as UTF-32 with the knowledge that an advanced compiler could choose to internally represent them as UTF-16 or even Latin1 to save space (JS implementations have optimized to convert their ropes from UCS-2 to latin1 when possible with huge memory savings as even Chinese sites are 90+% ASCII).
Module Typeclasses should keep typeclasses from happening everywhere (looking at you Haskell) while still allowing them to be used for more than equality.
Unofficial first-class functor support needs to be made official.
Pick one of the 4-5 slightly different concurrency models and standardize it.
Things I want that are in SuccessorML:
Guards, "OR" shorthand, optional leading pipe in matches
Line comments
Record punning, extending, and "updating"
do declaration shorthand
Maybe I'm missing something in SML, but OCaml has `ref` as well and it works just like SML's?
let x = ref 0
x := 12
print_int !x
> SML strings are immutable which lends itself to a lot of potential optimizations (and there's always byte arrays if you actually need to mutate).OCaml's strings are also immutable. They have been immutable by default since 2017 and prior to that one could opt into this behavior via a compiler flag.
2017 was just 3 years ago. Loads of Ocaml stuff rely on versions much, much older than that. In any case, the idea of outright changing a formerly mutable structure to an immutable one would be unthinkable in most languages due to all the breakages it is likely to cause.
In OCaml ref is defined as
type nonrec 'a ref = 'a ref = { mutable contents : 'a }
so it is an immutable record which contains one item which is mutable.> In any case, the idea of outright changing a formerly mutable structure to an immutable one would be unthinkable in most languages due to all the breakages it is likely to cause.
I agree with you. I started using OCaml in 2018 but I believe many linux distributions stayed on OCaml 4.05 (the release before safe-string was default) for a while because of breakages.
I was under impression that Haskell's typeclasses plus a couple of most common extensions minus the namespace pollution are pretty much equivalent to ML modules+functors, so could you elaborate how exactly that should work?
Here's some info if you're interested.
Also, Standard ML is, well, standardized. The standard isn’t perfect but it at least allows for a strong ecosystem of independent implementations.
MLton is a whole program optimizer (rather than function at a time like Ocaml) and wrings out a ton of performance though compile times are quite a bit longer.
As of 3 years ago it wasn't, but maybe that has changed.
Whole program compilation isn't without its downsides though. It seems pretty common to develop in SML/nj because of fast compiling then doing final performance profiling and deploying with mlton (having a standard helps). Function at a time is also more amenable to caching and reusing part of the previous compile.