There's also the new JVM option which eludes me at the moment which sweeps the strings which are promoted to the older generation and interns them.
Not certain about whether `String.intern` is permanently stored; I rather suspect that it sweeps the existing strings since iirc the java string has a hash associated with it anyway.
They require `sexp_of_t` and `t_of_sexp` because of their workflow being based on them; such as expectation testing [1] and tools such as [2]. It's a less noisy alternative to json for many people.
> You gave a beautiful answer about programming language
You do the same thing as in Rust, Scala or Haskell and derive the printer [1]. Then at the callsite, if you know the type then you do `T.show` to print it or `T.eq`. If you don't know the type, then you pass it in at the top level as a module and then do `T.show` or `T.eq`.
> Or to convert one type into another type?
If you want to convert a type, then you have a type that you want to convert from such as foo and bar, then you do `Foo.to_bar value`.
We can keep going, but you can get the point.
You _can't_ judge a language by doing what you want to do with one language in another. If I judge Rust by writing recursive data structures and complaining about performance and verbosity that's not particularly fair correct? I can't say that Dart is terrible for desktop because I can't use chrome developer tools on its canvas output and ignore it's hot-reloading server. I can't say Common Lisp code is unreadable because I don't have type annotations and ignore the REPL for introspection.
Okay...so you have to add a third party library to print? Yes, recursive data structures are a pain in Rust (well, recursive multi-owner data structures). But that's like comparing changing your oil to opening your car door. We do one of these a lot more. And bear in mind, I had to find this answer by googling and reading a random forum post. That's some pretty poor documentation.
And that's not talking about aesthetics. `T.show foo` or `Foo.to_bar value` is a lot of syntactic overhead for a rather common task.
And again, these are the lesser concerns to the other ones I outlined. Reading the code, building the code, and understanding the compiler errors are the big ones.
Not really third-party; ocaml-ppx is something similar to `javax` in the Java space? But it is optional and doesn't come bundled with OCaml.
Recursive structures are only rare in Rust _because_ they suck to write and have terrible performance characteristics in the language. In languages like Haskell, OCaml and Scala using tagless initial encodings for eDSL's [2] are really, really common.
I don't write Rust like I write any semi-functional language with function composition because, well, it's _painful_ and not a good fit for the language.
> `T.show foo` or `Foo.to_bar value` is a lot of syntactic overhead
The `T.()` opens a scope so OCaml code generally looks like:
```
let foo = T.(if equal zero x then show x else "not here")
```
Even when talking about usage, each language community for better or worse has a predefined workflow in mind. Your questions and workflow are specific to a particular language; you don't, for example, ask about the REPL, the compile times, debugging macros, the cold-start of the compiler, whether hot-reloading is a thing, the debugger, how it interacts with perf, how to instrument an application. Presumably because the language you use or the programs that you make don't have those components as part of their main workflow.
A lot of these things that you mentioned are valid flaws in Rust. I'm not going to dismiss them as not important or non-problems because they are genuine issues. Compile times suck. We could use hot reloading and a REPL. Debugging macros, instrumentation and perf stuff is good, but I assume it could be better. That's what I expect from a language community. Not constant denial about the state of usability. And it really does feel like many of the smaller language communities fall into this hive-mind where type signatures are valid documentation and who needs to use an editor other than emacs?
They are genuine issues, within Rust, but the way you /categorize/ the severity of the issue is different within language communities. They don't impact usability /much/ because of Rust's community, focus, size and niche.
Compile times in Rust are a problem, but the RLS does a good enough job of feedback and the development loop happens enough in compile time, that users don't miss it enough, compared to, say, Java which relies heavily on runtime behaviour/reflection for application behaviour.
Debugging token macros could be better, such as with a better macro-stepper, but you don't write enough macros in Rust to care heavily about it to make it a big deal, unlike in a Lisp.
Hot reloading would be nice, but not and ~essential~ part of development and deployment like in BEAM. Better reflection utilities might be nice but I doubt Rust libraries will ever be heavily dependent on it in the same way that Go or Java are.
If you are referring to OCaml, many people in the community care a lot about writing good documentation so that it's not just the type signatures. In fact the OCaml website team have made amazing leaps and strides integrating package documentation directly in the website.
And the experience using OCaml LSP Server with VSCode nowadays is honestly pretty good--type annotations displayed, error messages, go to definition, generating interface files. The core functionality is all there.
That's good to hear! I don't mean to be too negative. I'm genuinely glad that OCaml is making these strides. I'm hopeful that OCaml can find its equivalent of Esteban Küber[1] and they can make the language a truly fun and friendly experience.
You don't need a third-party library to derive a pretty-printer for your types, it just makes it simpler. OCaml takes the approach that the core compiler doesn't do any codegen, that is left to PPXs (basically, middlewares which transform code) which run before the compiler.
You can write a pretty-printer yourself using the conventions of the `Format` module. Is it manual and annoying? Yeah. That's why the PPX exists. It's a tradeoff.
> `T.show foo` or `Foo.to_bar value` is a lot of syntactic overhead for a rather common task.
A lot of syntactic overhead sounds like a stretch. I suppose you could drop the `T` like you do in Haskell but I personally like my language to be a bit more explicit. It improves readability.
Scala is probably not a good example because if you need some quick and dirty printing you can override toString and keep the rest of the generic code intact. In OCaml, Rust and Haskell you would have to add type constraints in a bunch of places to make println! T.to_string and show work.
The OCaml object system is still parametric polymorphism (trying to pass itself as subtyping polymorphism through row variables) rather than ad-hoc polymorphism: there are still no functions that only work on a finite subset of types. In other words, a function may work on any objects that has a method `m`, but you cannot have the same method that has different implementation for `int` and `float`.
It uses structural typing not ad-hoc polymorphism. Plus it’s rarely used and it used to give hard to parse error messages when you made type mistakes. I don’t really see it as an adequate replacement for ad-hoc polymorphism.
> No standard and easy way of implementing interfaces
Firstly another commenter has mentioned [1] modules as interfaces. There is also the object system [2] which I've seen used to great effect in similar scenarios.
Typeclasses and modular implicits are fantastic - being a heavy user of Scala and Rust; but I've always found that they tend to be best when used as an alternative to macros, for derivation purposes.
The interface and code split in OCaml is also really nice for value types and comes with no limitations; for years, we had issues in Scala because of the host platform, and in Rust exposing functions for your newtype can be oddly boilerplate heavy.
> Bad standard library
The OCaml standard library is (infamously) anemic and obviously is not as fully-featured as something like Java or Python, but since alternative libraries tend to be compatible with the bundled StdLib (both use the same `option` and `list` type), it means that having libraries dependent on different ones is not a huge issue. Learning resources, can be confusing though.
I'm not sure why it's a problem certain data structures are mutable and some are persistent; the documentation is usually fairly clear and you usually have a performance characteristic in mind when selecting your data structure.
Universal equality and hashes are indeed a little annoying (here an `Eq` typeclass would be great!) but I do understand the original decision to have them inside. At the very least, it's not pointer based equality and since records and most types don't have subtypes, you don't run into as many issues. You can of course use the equality methods on the modules themselves and since `Hashtbl` and co have functors, you aren't penalized for it.
Strings are a problem-ish (what older language doesn't have string issues ha!), but there is utf-8 support now with [3].
> but just two years ago it was common to use Makefiles to build OCaml projects
It is true that OCaml has a unix-y flavour, but honestly I don't really understand the snipe at make. Sure there are alternatives, but make is bundled on most distros, has a quick startup time and a lot of people are familiar with it.
More of the community is moving towards dune as well, which is pretty good; the docs could do with better indexing but there are some features such as promotion which are really nice.
> was no standard way of doing compile-time metaprogramming
I haven't used ppx much so I can't really comment here.
Finally they've missed the biggest reasons to /use/ OCaml.
To be fair to the OP, they said they kept asking for more concise recipes and they acknowledge they'd only use it as a shopping list. We don't know what the less concise recipes looked like but there's no reason to assume they would be particularly bad. There must be literally tense of thousands of examples of carbonara recipes on the web...
I have seen this technique (send all the indexed search terms) a few times in the wild. Racket (a scheme derivative specifically made for teaching) has a search page where everything public is indexed [1] (see plt-index.js) and it works really well.
The most horrible part is that _they are allowed to drop their case anytime_ in the UK civil court. In previous cases when the accused has run out of money, the defendants have to pay their costs [1] to keep the trial running - with zero chance of being able to recoup costs because the accused will be bankrupt anyway. The UK state should not make private individuals fund the creation of novel case law; it's absolutely stupid.
> The UK state should not make private individuals fund the creation of novel case law;
If you read the appeals decision (and the decision that granted the permission to appeal)-- that seems to very much be the motivation here too: Case law on this subject would be intellectually interesting and potentially important in the future, so lets leave these foreign defendants on the hook to help establish it.
Beyond the ethical problems with that position to begin with, this is a terrible case to try to establish anything because it's so factually conflated that all the resources are going to go to sorting through the plaintiffs lies. The defendants don't have any particular interest in the UK establishing good law except to the extent that bad law in the UK may have international ramifications. (and even there not much-- defendants aren't businesses, they're volunteer developers many (most?) of whom have already quit participating)
Emacs launches processes on the `PATH` so using `direnv`, you can change the `PATH` to the version of `rust-analyzer`/`gopls`/`python`/`psql`/`protoc` that you're using as well as setting the correct load paths for each language.
Not certain about whether `String.intern` is permanently stored; I rather suspect that it sweeps the existing strings since iirc the java string has a hash associated with it anyway.