Types
Stof type system.
There are two primitive data types: scalar and compound. Stof also has an "unknown" type, union types, a "data" or "Data<My Data>" type for custom or complex data, a semantic version type, and a prototype system for objects.
Types add consistency and stability to your code in such a dynamic environment. For times when you need dynamic capabilities, "unknown" matches any type and allows you to type-check data yourself.
For fields and variable declarations, types are implied by value. However, if you define a type, the field or variable will maintain that type, casting values to that type when assigned.
Scalar Types
A scalar type represents a single value. Stof has 5 primary scalar types: integers, floating-point numbers, booleans, strings, and blobs.
Stof also has functions, data pointers, objects, semantic versions, and promises as types too, but we'll see those later on.
Integers
An integer is a number without a fractional component. Stof has one integer type, which is an "int". This is a signed 64-bit integer.
int field: 42
#[main]
fn main() {
let var: int = -42;
const val = +1_000_000; // readability
let hex = 0xFf; // int hex = 255;
let bin = 0b0011; // int bin = 3;
let oct = 0o55; // int oct = 45;
}Floating-point Numbers
A floating-point number is a number with a fractional part. Stof has one floating-point type, which is a "float" - a 64-bit signed floating-point number (f64).
Unit Types
Stof also has a variant of a floating-point number for units. Units can act as types on their own and are outlined in greater detail on the Numbers page.
For example, the function Time.now() in the Time Library (Time), returns a floating-point number with units of "ms". The unit "ms" can be used in place of the type "float" as a more specific type of number, enabling conversions when the number is cast.
All unit types match the type "float" (Ex. function parameter).
Booleans
Booleans can have one of two possible values: true or false.
Strings
String literals can be declared using either double or single quotes. Or with a raw string syntax r#".."#, which accepts multi-lines and does not escape characters.
Strings can also be constructed with a template syntax:
Blobs
A blob in Stof represents a Vec<u8> (Rust) or Uint8Array (JS). For large amounts of data, this is a lot more efficient than a list.
Blobs are useful for representing abstract binary data or as an exchange between APIs or data types.
Compound Types
Compound types group multiple values into a single type. Stof has four compound types: tuples, lists, maps, and sets.
Tuples
A general way of grouping types into a singular value.
Lists
A list can grow and shrink in size, is unordered, and can be manipulated at both the front and back.
Sets
A set can change in size, is ordered, and can not contain duplicate values.
Maps
Maps can also change in size, are ordered, and cannot contain duplicate keys.
Prompts
A prompt in Stof is a string with an optional XML tag and child prompts (a tree structure). It can be treated like a string when needed, or as a tree when building/maintaining.
The prompt type is useful when working with AI workflows in Stof.
Before the prompt type was added to Stof in v0.8.47, it was common to use a small #[type] object for building prompt trees. It would have the fields "text", "tag", and a list of child prompts.
Its output would be the text and any child prompt outputs pushed together, all wrapped in the XML tag if present.
This was so common that it made sense to make it a primitive type, removing the memory management overhead and making working with AI much more human-friendly and maintainable.
Semantic Version
Versioning is an important aspect of APIs, and because Stof is so useful for defining, combining, and interfacing with APIs, it has a built-in version type. See Semantic Versioning for more information on versions.
Unknown
The "unknown" type is needed in Stof, where languages, data, and APIs come together dynamically. Especially useful in use cases like schemas, dynamic field transformations, or when you're not sure what type of data you'll receive in a function call.
The "unknown" type is just syntax for "match with any type". Each value always has a type, so when using "unknown" (or union types), make sure to check types yourself to ensure operations do not result in an error.
Union Types
Union types are generally preferred to the "unknown" type, acting as an OR filter for matching types.
Promises
Stof supports asynchronous data manipulation and, therefore, has a promise type. A promise holds a reference to another Stof process, and when awaited, will wait for that process to finish executing before returning its result.
The promise type matches its inner type, and "await" is a passthrough operation unless the value is a promise. This means you rarely need to write out the "Promise<inner>" type - you can just use "inner" in its place.
Data
As outlined in the How Stof Works, Stof organizes a lot of different types of data, even custom types. The "data" type is an opaque pointer to any data that exists on a node (object). This includes functions and fields, but also data that you could define yourself, like a PDF document, Image, or anything you'd like.
We'll go over the data concept in greater detail later on in the book.
Complex Data
The "data" type matches all data; however, Stof has a "Data<..>" syntax for matching specific types of data, even custom types that you add yourself.
This is nice, because you can have large data types as multiple fields, passed around between functions, etc., with no overhead.
"data" matches the type "Data<Pdf>", but "Data<Pdf>" will not match the type "Data<Image>". Think of these complex data types as a subtype or specific type of "data".
Objects
Objects in Stof have an "obj" type. Behind the scenes, they reference nodes and can contain much more diverse data types than just fields and functions.
The map constructor syntax {"key": "value"} looks like the object syntax, but they are two completely different types.
Prototypes
Objects in Stof can be used as prototypes for other objects. There is a special #[type] attribute for objects that, when the parser sees it, it will create a typename link to that object.
Take a look at Prototypes for more information.
Null
Yup, Stof has a null value type. So many data formats and languages have null, that for interoperability, it was unavoidable.
Not Null Types!
There is a way to combat this, though - ensuring an error is thrown when a null value is given where it shouldn't be.
The answer is a "not null" type operator 🎉! Not a perfect solution, but it helps a lot.
The ! postfix type operator works with all types, anywhere. So use with object prototype names, units, etc.!
Also handy to use this on a return type, ensuring a function does not return null.
Last updated