Well, I've translated about 15kLOC of OCaml/OpenGL to F#/DirectX now: my Smoke vector graphics engine. The translation has been amazingly painless, especially considering the commercial benefits of opening the Windows market.
Smoke's basic design revolves around a scene graph that appears to be purely functional to the user but actually caches as much as possible to improve performance (this is why Smoke is 10x faster than Microsoft's Avalon, Adobe's SVG viewer and Macromedia's flash for complex scenes). I've skipped most of this translation because DirectX lacks a lot of vital functionality compared to OpenGL, specifically display lists (that transparently compile static geometry and upload it to the graphics card) and a tesselator (that converts winding-rule polygons into triangles).
I spent two weeks tracking down a really annoying bug. This bug manifested itself as access violations from Managed DirectX (not supposed to be possible!), corrupted IL (also not supposed to be possible) and weird-looking corrupted renderings. I originally blamed the problem on Windows Forms not being thread safe. Having scoured the docs for information on that I started to blame Managed DirectX.
As it happens, the problem was caused by an innocuous-looking closure in my F# code. I had replaced a cached OpenGL display list with a cached closure that would render a geometry. However, different visualisation windows can share the same scene graph and, particularly, the same caches. And this cached closure was caching the DirectX device that it was rendering to. Consequently, the OnPaint method of one window, running in one thread, was trying to write to a device that belonged to another thread. Hence the corruption. It seems that DirectX doesn't check for this and, consequently, it was sometimes resulting in memory corruption.
Aside from this one annoying bug, the ability to perform computations concurrently in F# is nothing short of miraculous. My immutable OCaml code runs concurrently with no changes. I only used immutable data structures four times in 15kLOC of code. Once I had wrapped these with locks, to prevent different threads from accessing them simultaneously, the entire 15kLOC was ready to exploit my dual core system. Sure enough, performance is almost doubled!
There's no way this could have been done in two weeks had I been using C++ or C#...
I'll upload a demo showing the graphics capabilities of my libraries ASAP. In the mean time: happy hacking!
Background reading on the reference counting vs tracing garbage collection debate - Eight years ago I answered a question on Stack Overflow about the suitability of OCaml and Haskell for soft real-time work like visualization: "*for real-ti...
1 month ago