Hacker News new | past | comments | ask | show | jobs | submit login

F# seems like such an amazing language every time I look at it — a modern version of OCaml, with a clean syntax, some novel ideas, and fewer legacy warts.

However, I wish that it had, like OCaml, a native AOT compiler that didn't come with the baggage of the .NET runtime. Some people might consider this a benefit, not baggage, of course. But it's the same reason I'm put off by Scala.

From what I understand, to even run a compiled F# program you have to have Mono installed? It does look like you can get AOT compilation with Mono [1], but the limitations (e.g. no generics, apparently) seem too onerous.

[1] https://www.mono-project.com/docs/advanced/aot/




After being deeply burned by the .NET framework, I consider OCaml significantly superior to F# just because it doesn't depend on .NET or Microsoft.

And yes, somehow the OCaml guys have managed to implement generics and AOT compilation to optimized machine code long before the .NET framework existed, but now this is something "truly hard" on .NET.


My problem with OCaml that while the semantics are top notch, everything else is stuck in the past.

The syntax is quirky, there's a bunch of legacy baggage (does anyone use the OO stuff?), there's no SMP support (though I know this is being worked on), the toolchain feels antiquated (the REPL still, to this day, doesn't come with Readline support built in; rlwrap is required!), etc. Not to mention the lack of modern libraries, frameworks, package management, etc.

Reason and BuckleScript are nice, though. Reason cleans up a lot of my complaints, while still not being quite as elegant as F#. But there's this sense that nobody really wants to make any groundbreaking effort here; there doesn't seem to be any push to make Reason a first-class, new syntax for OCaml, so it's stuck being a web-oriented veener for new users, while old "industrial" users like Jane Street are content to continue with their thing.


Example of OCaml's object system in use by the creator of OCaml: https://github.com/xavierleroy/cryptokit/blob/master/src/cry...

OCaml's object and class systems are excellent; I prefer them to just about anything else. They rarely get used for the simple reason that algebraic types, functors, and first-class modules are better suited to modeling almost any kind of domain logic.

Also, I like OCaml's extremely simple and direct syntax. I'm fine with F#'s implicit `in`, though it requires whitespace-sensitivity. I think ReasonML went in the wrong direction, cluttering it up with curly braces and ubiquitous tuple-like syntax for function arguments.

OCaml actually has excellent tooling — among the best — and some (but not many) great libraries. What it lacks most is great documentation...


>OCaml actually has excellent tooling — among the best

I don't think even the core OCaml devs would claim this. Rust (and Java and Microsoft) toolchains are examples of excellent tooling. OCaml, not so much.

That said, the tooling situation today in OCaml is much better than it was a few years ago, which is real progress.


Yes and no. OCaml already has one of the fastest production compilers in the world, acceptable error messages (better than Haskell's, anyway), a great REPL (utop), a high-quality and well-documented build system (dune), a powerful package manager (opam), and a very good language server for IDE integration (merlin).

What it's sorely missing right now is higher quality documentation output. Currently, it's hard to navigate the generated documentation (e.g., no search bar), it's not held in a centralized online location, and it doesn't do a great job dealing with complex module/functor hierarchies (especially in the presence of destructive substitution).

Unfortunately, much of what I described above doesn't come out of the box. To fix this, the OCaml community is seeking to emulate Rust's cargo tool via the development of the ocaml-platform: http://ocamllabs.io/doc/platform.html

An aside: I didn't know Java had good tooling. I know it recently gained a good REPL. But what is the official package manager, and where is the centralized repository for packages?


I believe Maven is Java's package manager these days.


Thanks for the example. That's a very nice use of OO, I like it!


I think modern OCaml's toolchain is quite nice — Dune, OPAM, Utop, OCaml/ReasonML support for VSCode. I am a newcomer to OCaml world, but so far it's been great for me.


Can you describe how you were burned by the .NET framework?


Its part of dotnet core, so you don't need Mono installed. And you can build a self-contained dotnet core application so you don't need core installed to run it.

AOT is possible via something like CoreRT, but its still a bit beta and not straightforward. From my experience the only limitation with CoreRT and F# is certain reflection heavy functionality. No problem with generics.


Well, if not Mono, then the .NET Core runtime package, right? It's not self-contained. I read this [1], but it's unclear to me how I build a self-contained binary, or what options are available for AOT.

[1] https://github.com/dotnet/core/blob/master/Documentation/sel...


If you build with 'msbuild publish -r debian8.x64' or any of the other valid 'runtime identifiers', the output of the build is an xcooy-deployable folder that contains your binary and all it's dependencies including the runtime. I use this at work to make Debian packages that are standalone.


The command you are thinking of is probably `dotnet publish -r debian.8-x64`


Cool, thanks!


AOT not supporting generics? that's a pretty bad reading/summary of the webpage you link to (not to mention, that page may be a bit outdates, and more cases are supported by AOT now; take in account this is the mode that iOS apps developed with Xamarin need to use).


In dotnet land generics are JITted on demand at runtime when you first execute a specific instance of that generic type.

So List<int> doesn't necessarily get JItted even though List<long> has been. This poses a bit of a problem for AOT compilation.

You would essentially have to either

A) Trace all possible execution paths and determine every needed generic instantiation and precompile and ship them all. This ain't easy, and it might be impossible. Also expect massive binaries due to all those types.

B) Bundle a JIT and lazily emit code as needed.

C) No generics?


Note that since Windows 8, .NET Store apps are fully AOT to native code, there is no JIT.

Window 8.x used the cloud compiler with MDIL deployments (based on Bartok MDIL from Singularity), doing on-device linking.

Windows 10 makes use of .NET Native toolchain.

The only restriction is reflection, all classes that are accessed via reflection need to be explicitly mentioned on a rd.xml file, otherwise the linker might prune them.


> So List<int> doesn't necessarily get JItted

It does, if the AOT compiler is advanced enough to examine all code and determine that `int` is a possible type being used with List<T>. Mono has had a lot of advancements on these techniques over the years, as it's the only way for them to let Xamarin devs deploy apps on the iPhone.


In regular .NET you can instantiate generic types with a type parameter provided at runtime.

Of course it's not something you should ever do in regular code, but it can be useful for deserialization and stuff like that, so you can create e.g. a list of arbitrary types received over the wire.

Does the AOT compiler just crash if asked to compile a project that uses reflection?


"As of Mono 2.0, AOT compilation is only supported for non-generic methods. support for generics is currently under development."


This was outdated info on the website, I've updated the page. Generics are supported with FullAOT nowadays.


Mono 2.0 is ancient, nowadays the version is 5.16. That webpage is not worth looking at.


So where should I look? It doesn't seem to be a particularly popular or well-documented topic. The best I've found is this [1].

[1] https://mattwarren.org/2018/06/07/CoreRT-.NET-Runtime-for-AO...


Right, maybe the best way to figure out its completeness is just testing it. AOT has received a lot of love these days, the runtime accepts many flags when dealing with it, e.g. "fullaot".


FYI a Mono dev removed those old statements about AOT+generics from the page because he agreed with me that they were outdated.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: