Start

Getting started

Add a .hb file to a C# project, open the Prelude, and call a compiled formula.

Hilbert is used from an ordinary .NET project. You put .hb files next to your C# files; at build time the hilbert compiler reads every one of them and writes a C# class per file into Generated/Hilbert/. Your code calls those classes like any other.

Availability. Hilbert is currently distributed as source, as the modules/MLambda.Hilbert submodule of the MLambda Genesis workbench — there is no NuGet package yet. The repository is not buildable on its own clone; build it inside a Genesis checkout as shown below.

1. Get the source

git clone --recurse-submodules https://github.com/mlambda-net/MLambda.Genesis.git
dotnet build MLambda.Genesis/modules/MLambda.Hilbert/MLambda.Hilbert.slnx

An existing Genesis checkout only needs git submodule update --init modules/MLambda.Hilbert.

2. Wire a project

A project that contains .hb files needs two things: a reference to the runtime (the objects the generated code is written over) and an import of the build targets (the step that runs the compiler). The compiler itself is a build-time tool and never a run-time dependency.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <OutputType>Exe</OutputType>
    <RootNamespace>Shop.Analytics</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\MLambda.Hilbert\src\MLambda.Hilbert.Runtime\MLambda.Hilbert.Runtime.csproj" />
  </ItemGroup>

  <Import Project="..\MLambda.Hilbert\src\MLambda.Hilbert.Compiler\MLambda.Hilbert.targets" />
</Project>

Adjust the relative paths to where your project sits. The targets understand three optional properties:

Property Default Meaning
HilbertNamespace $(RootNamespace) Namespace of the generated classes.
HilbertGeneratedDir Generated/Hilbert Where the .g.cs files are written.
HilbertMaxDepth 1000000 How many turns a recursive definition may take before it is reported as a fault.

Every .hb file under the project directory is an input, and a changed Prelude re-runs the step.

3. Write a formula

Create Angles.hb:

-- Angles.hb — definitions are mathematics; fn is what a program calls.

def radians(d) ≔ d · π / 180
def degrees(r) ≔ r · 180 / π

fn toRadians(a) ↦ radians(a)
fn toDegrees(a) ↦ degrees(a)
fn sum(x, y) ↦ x + y

radians and degrees are definitions: they are inlined wherever they are used and folded by the compiler, so no π / 180 is computed at run time. toRadians, toDegrees and sum are doorways: each fn becomes a public static method of a class named after the file.

4. Call it from C#

using Shop.Analytics;

Console.WriteLine(Angles.ToRadians(180));                         // 3.141592653589793
Console.WriteLine(Angles.ToDegrees(Math.PI / 2));                 // 90
Console.WriteLine(Angles.Sum(1, 2));                              // 3
var v = Angles.Sum(new[] { 1d, 2d }, new[] { 2d, 5d });           // [3, 7]
var w = Angles.Sum(10, new[] { 1d, 2d });                         // [11, 12] — a real broadcasts

One line of Hilbert produced overloads for double, Complex, Vector, Matrix and Tensor, and every mix of a real with a shaped value. The outputs above were produced by compiling and running this exact file.

5. Open the Prelude

The Prelude is Hilbert’s standard library. A module is brought into a document with open:

open Prelude.Statistics

fn average(x)   ↦ mean(x)
fn deviation(x) ↦ std(x)
fn midpoint(x)  ↦ median(x)
var avg = Summaries.Average(new[] { 1d, 2d, 3d, 4d });   // 2.5

One name is one formula. A document may not declare a name that any module it opens already declares. fn median(x) ↦ median(x) is refused with HB0001 'median' is already declared in Statistics.hb — give your doorway its own name, as midpoint above.