static typed functional programming

Form gives you a powerful static type data modelling system. Because it is statically typed, types are known at compile-time making compiler optimisations easy. This allows the runtime to be fast while keeping the behavoir of your programs easier to reason about.

def my_int int def new_strct_type {unsigned mmbr1, unsigned mmbr2} def two_strings {[char] a, [char] b}

Form includes all of the basic types (int, float, char etc), as well as many compond types such as growable lists, structure and optional types.

new_strct_type strct = {10, 15} [char] str = "the form programming language" [unsigned] lst = [0, 5, 10, 15, 20, 25] int? optint = +9


Constraints provide a concise syntax that allows for features such as function composition and backtracking. In form all functions are called using the constraint syntax.

{long a, long b} -> min : if this.a < this.b : return this.a return this.b;

For example the above function can be called using the following constaint call.

mutable [[char]] -> main -> int : smaller = {50l, 18l} -> min return +0;

Here {50l, 18l} is constrained to type min, this, using the form solver, calls the function {long a, long b} -> min.

Because form can destinguish mutable and immutable functions, constraints are often resolved to constants, completely removing unneeded function calls.

Form includes a handful of inbuilt immutable list processing functions making the use of lists fast and safe.


Form includes a full template system for both template types and function templates.

def my_data<:T, U:> {int, unsigned, T, T, U} def optional_type<:T:> T? def list<:T:> [T] {[%T] lst, unsigned idx} -> template_function<:%U:> : <> a template function return this.idx; [%T] -> merge_sort : <> sort the list using merge sort... return this;

type inference

Type inference is used all over form, meaning you don't need to specify return types/variable types if the type can be deduced from context.

{int a, int b} -> min : if this.a < this.b : return this.a return this.b; mutable [[char]] -> main -> int : smaller = {50l, 18l} -> min return +0;

Here the return type of min and the type of smaller are inferred. Type inference works with the template system to make using types easy.

data modelling

Because of the power of form's type system application data can be defined easily. With templates, creating functions that handle application data is easy.

def vector<:T:> {T x, T y, T z} def application_data { unsigned unsgn1, unsigned unsgn2, float flt1, float flt2, char chr, double dbl, vector<:float:> vec, [unsigned, unsigned] lst} mutable %T -> appdata_processing<:%U:> : <> modify the application data return this; mutable [[char]] -> main -> int : application_data appdata appdata = appdata -> appdata_processing<:float:> return +0;

control flow

Form has all of the familiar control flow that users know from other programming languages, such as if..elseif..else, switch...case, for, while and do...when.

include "stdio" as stdio mutable [[char]] -> main -> int : a_str = "this is a character list\n" if a_str -> size == 15 : "a_str is 15 char long\n" -> stdio.print elseif a_str -> size == 25 : "a_str is 25 char long\n" -> stdio.print else "a_str is not 15 or 25 char long\n" -> stdio.print; switch a_str -> size : case 15 : "a_str is 15 char long\n" -> stdio.print case 25 : "a_str is 15 char long\n" -> stdio.print default "a_str is not 15 or 25 char long\n" -> stdio.print; for x in a_str : <:int:>x -> stdio.putchar; i = 0 while i < (a_str -> size) : <:int:>stdio[i] -> stdio.putchar ++i; i = 0 do <:int:>stdio[i] -> stdio.putchar ++i when i < (a_str -> size) return +0;


Language Release - 1.0


Version 1.0 released

Downloads, Release Notes

Documentation Added


New documentation created, including a getting started guide, documentation covering all of the inbuilt functions and standard library functions.


Associates & Users

Become An Associate
© Eyra Software Systems Ltd