Getting Started

Welcome to Functal! Functal is an easy to use language for writing expressions with programming logic mixed in. Following this quickstart guide will get you up and running with your first expression in no time! The rest of the documentation covers all the concepts introduced here in more detail.

Installation

Functal is a .Net Standard 2.0 Library. It can be added your project by adding Functal.dll as a dependency. For example, in Visual Studio 2019:

  1. In the Solution Explorer, right click the References or Dependencies item and click Add Reference. This opens the Reference Manager.
  2. Click Assemblies on the left side of the Reference Manager, and then click Browse.
  3. Navigate to where you have saved Functal.dll and click Add.
  4. Click OK.

You're now ready to use Functal in your .Net projects!

The Functal Language

Functal expressions are made with a the following main components:

We'll introduce the important ones below, and for more detail see the Language Fundamentals section. For the most part, their syntax and semantics are much the same as other languages you've used before. The key difference is they are used to write single line expressions, rather than large programs.

So something as simple as this is a Functal expression:

1 + 2 * 3

But you can up the ante like this:

int(Sin(Pi)) + BezierCurve(1f, 2.5f, 3f, 0.5f)

or this

Math.Pow(2.5f, if(LengthOf("This String" + "That String") < 10, 2, 3))

or even this:

[MyInteger] + [MyFloat]

That last expression used parameters, which are kind of like variables. More on that below.


Compiling and Running Expressions

Compiling an expression is easy, and can be done in a few lines. Copy this snippet into a C# Console Application to see for yourself:

using System;
using Functal;

public static class Program {
  public static void Main(string[] argv) {
    FunctalExpression<int> expression = new FunctalCompiler().Compile<int>(
      "LengthOf(\"Hello, world!\")"
    );
    Console.WriteLine(expression.Execute());
    Console.ReadKey();
  }
}

Expected Output: 13

Line 5 is the important one. A FunctalExpression returning an int is defined. Next, an expression is provided to the compiler as the string argument LengthOf("Hello, world!").

It's important the expression being compiled matches the expected return type of the expression. They don't have to match exactly if an implicit conversion exists between the output type of the string and the target type of the FunctalExpression. For example, the expression 1 + 2, which would return an integer, can be compiled into a FunctalExpression<float>.

Once the expression is created, it is executed (line 6), and the output of the script is printed.


Parameters

One of the examples above looked a bit different to the others:

[MyInteger] + [MyFloat]

This example used parameters. Parameters are similar to variables in other languages, and allow you to pass data between expressions and the parent program. Parameters are declared in C# using an FnVariable object, and passed into your script during compilation. You can reference a parameter in Functal using its name surrounded by square brackets, [LikeThis].

Once compiled, you can change the value of the FnVariable in C#, and this will change the output of your expression when run again. For example:

using System;
using System.Collections.Generic;
using Functal;

class Program
{
  static void Main(string[] args) {
    FnVariable<int> MyInteger = new FnVariable<int>(1);
    FnVariable<float> MyFloat = new FnVariable<float>(2.5f);

    Dictionary<string, FnObject> parameters = new Dictionary<string, FnObject>() {
      { "MyInteger", MyInteger },
      { "MyFloat", MyFloat },
    };

    FunctalCompiler compiler = new FunctalCompiler();
    FunctalExpression<float> expression = compiler.Compile<float>(
      "[MyInteger] + [MyFloat]", parameters
    );

    Console.WriteLine(expression.Execute()); // Output: 3.5

    // Changing the value of the FnVariable changes the output of the expression!
    MyInteger.Value = 5;
    Console.WriteLine(expression.Execute()); // Output: 7.5

    Console.ReadKey();
  }
}

Creating Custom Functions

Functal has a library of functions built in. If you need more however, you can add them yourself. Functions are defined in C# and called in Functal. Here's an example:

using System;
using System.Collections.Generic;
using Functal;

/// <summary>
/// Returns true if the specified number is less than 5, false if not.
/// </summary>
class FnFunction_IsLessThanFive : FnFunction<bool> {
  /// <summary>First argument: The number to check.</summary>
  [FnArg] protected FnObject<int> Number;

  public override bool GetValue() {
    return Number.GetValue() < 5;
  }
}

class Program {
  static void Main(string[] args) {
    // Add custom function to Functal.
    FunctalResources.CreateFunctionGroup("IsLessThanFive");
    FunctalResources.AddFunctionToGroup("IsLessThanFive", new FnFunction_IsLessThanFive());

    FunctalCompiler compiler = new FunctalCompiler();

    Console.WriteLine(compiler.Compile<string>(
      "\"First Result: \" + ToString(IsLessThanFive(3))", parameters, null
    ).Execute());

    Console.WriteLine(compiler.Compile<string>(
      "\"Second Result: \" + ToString(IsLessThanFive(7))", parameters, null
    ).Execute());

    Console.ReadKey();
  }
}

You can even create overloads by adding more functions to the same group.


Next Steps

Check out the Language Fundamentals to get an understanding for how Functal works and it's individual pieces. For detailed information on the C# API, take a look at the C# DLL Reference.