Sunday, February 19, 2017

Yes, Virginia, You Can Write HoloLens Apps in F#

[Unfortunately, after this post was written I discovered incompatibilities which pretty much kill the idea of writing HoloLens applications in F#. See "No Virginia, You Can't Actually Write Unity Apps for HoloLens in F#" for details.]

F# fans who want to write applications for the Windows Store have been disconcerted by this thread on GitHub, which indicates that .NET native doesn’t support all the IL that F#’s compiler can generate. That seems to throw cold water those of us wanting to write HoloLens applications in F#, since applications for HoloLens have to be UWP apps for the Windows Store.
This is a big deal. The HoloLens platform is going to be a huge draw of new developers to the Microsoft community; people who want to be on the cutting edge want to use cutting-edge tools. In the most recent Stack Overflow poll of developers, F# came out the third most loved programming language, behind Rust and Swift. I can believe it. Programming in F# makes me happy.
I was overjoyed to discover that there is a fairly straightforward way to write 3D HoloLens applications in F#, as long as you’re using the Unity 3D game engine. Unity comes with two “scripting backends” that incorporate developers’ .NET code into a Unity3D app. One of these scripting backends is called “IL2CPP.” When it is used, the IL in .NET assemblies used by the Unity project — including F# assemblies — is translated into C++, which is then compiled to .NET native code. Unity has said that IL2CPP is the future of scripting in Unity.
To use IL2CPP for Windows Store apps, you have to be using Unity on Windows, and you have to have the IL2CPP scripting back end installed. (It’s one of the options when you install Unity). Then, in Build Settings > Player Settings choose the Settings for Windows Store tab and look under Other Settings > Configuration > Scripting Backend and select IL2CPP.
To code in F# for Unity, the basic idea is that you compile your F# code into a DLL (targeting .NET 3.5), and then have a post-build step copy the DLL and the FSharp.Core DLL into the Assets\Plugins folder in the Unity project. The classes inside the DLL show up in the project window and can be dragged onto Unity components just like scripts. (For more details, see Jackson Dunstan’s tutorial.)
The GitHub thread mentioned above says that one of the blocks to getting F# support for UWP is that tail call optimization isn’t supported by .NET Native. What happens when we instead translate the IL to C++ using IL2CPP? I tested this tail call to see what would happen:
 let rec callTailRecursiveFunction index =
       if index  callTailRecursiveFunction

IL2CPP turns it into this:
extern "C" void MyClass_callTailRecursiveFunction_m1362434375 (MyClass_t1938649317 * __this, int32_t ___index0, const MethodInfo* method)
  {
  IL_0000:
    {
       int32_t L_0 = ___index0;
       if ((((int32_t)L_0) > ((int32_t)0)))
       {
         goto IL_0006;
       }
     }
     {
       return;
     }

  IL_0006:
     {
       int32_t L_1 = ___index0;
       ___index0 = ((int32_t)((int32_t)L_1-(int32_t)1));
       __this = __this;
       goto IL_0000;
     }
   }
Which seems to indicate that, in this case at least, tail calls are optimized.
I haven’t done exhaustive testing so there may be other aspects of F# IL that IL2CPP has trouble with. But I have been able to get a small demo app running with the scripts all in F#.
Hopefully full UWP support for F# is not far off. But it’s great that the Unity folks have made it possible for us to be writing HoloLens apps in F# right now.
[This post was originally posted here.]