Link Search Menu Expand Document

Oters - Program Structure


Oters draws heavy influence from the OCaml language and this is quite apparent in its program structure. Moreover, since at its core it is a Rust library much of the syntax is inspired by Rust as you shall see here. Oters programs are made up of the following 6 statement types:

  1. use: These import functions and types from other files or the standard library.
  2. type: Like Rust’s type statements, they simply alias types so that you can use them in the declarations of structs and enums.
  3. struct: Speaking of which, structs in Oters are like Rust structs and defined in the same way.
  4. enum: These are also the same as Rust enums albeit with slightly different syntax.
  5. let: These define variables and functions.
  6. let ... and ... with: These define mutually recursive variables.

Example

use std::stream::map

type Stream<A> = (A, @Stream)

enum Option<T> {
	Some T,
	None,
}

struct Color {
	r: int,
	g: int,
	b: int,
	a: int,
}

let from = fn n -> n << @(from (n+1))
let nats = from 0
let evens = map (fn x -> x *2) nats

let chicken = map #(fn b -> if b then 0 else 1) egg
and egg = map #(fn i -> if i == 1 then true else false) chicken
with false

A program simply consists of a series of these expressions without any separation tokens between them. That’s right, you don’t need a semi-colon in between each statement. There is a limitation, however, and that is that any value or type must be placed below the definition of any other value or type that it references. So in the example above, we could not place nats above from or even above nats.

Functional Reactive Programming

The precise syntax and semantics of these expressions are found in subsequent sections of this documentation. Nevertheless, I would like to introduce here the concept of Functional Reactive Programming (FRP), the paradigm under which Oters falls.

Functional Reactive Programming aims to capture the changing state and reactive behavior of a program through the ‘Stream’ type. Streams are a recursive, polymorphic type, similar to lists, composed of a head that holds the stream’s value at the current time step, and a tail that holds a reference to the future values of a stream.

\[Stream\ A \equiv A \ll Stream\ A\]

For example, in the example above, which you don’t need to understand fully yet, the values nats and evens are streams of integers.

The main thing to take away from this is that Oters programs are inherently temporal. Most of the values you will define will be either streams or functions that transform them. When you run the program, the interpreter will take care of evaluating and updating all the streams you will have defined automatically. Thus, Oters programming can be summarized as declaratively describing how streams of values change with time.