Data Types
The Cajá language is strongly typed, ensuring that data is managed predictably and safely. This page covers the primitive data types, collections, and how to define custom structures.
Primitive Types
Cajá supports four core primitive types:
Number: Represents all numeric values, including both integers and floating-point numbers.String: Represents a sequence of characters, enclosed in double quotes.Boolean: Represents a logical entity and can have two values:trueorfalse.Date: Represents a specific point in time (usually instantiated and manipulated using the built-indatemodule).
let count: Number = 42
let birthday: Date = '2002-04-05'
let name: String = "Cajá"
let isActive: Boolean = trueArrays
An array in Cajá is a collection of elements that share the same type. Array types are denoted by enclosing the element type in square brackets, such as [String].
let fruits: [String] = ["apple", "banana", "orange"]
let scores: [Number] = [100, 95, 80]Multidimensional Arrays
You can create 2D arrays (or arrays of any $n$-dimension) by nesting the brackets. For example, a 2D array of strings is typed as [[String]].
let matrix: [[Number]] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
let board: [[String]] = [
["X", "O", "X"],
["O", "X", "O"]
]Maps
A map (or dictionary) associates unique keys of one type with values of another type. The type signature for a map is map[KeyType]ValueType.
Note: A map in Cajá only accepts three types of keys:
StringNumber- A custom
structthat contains akeyproperty of typemap.KeyFunc(which has afn() -> Stringsignature).
You can initialize an empty map using {} and assign values to it using bracket notation.
import map
let ages: map[String]Number = {}
ages["Alice"] = 28
ages["Bob"] = 34
let userScores: map[Number]Number = {}
userScores[101] = 99
# Using a struct as a map key
type CustomKey struct {
key map.KeyFunc
value String
}
let cache: map[CustomKey]Number = {}
let myKey = CustomKey {
key: fn() -> String { return "key_id_1" },
value: "Some data"
}
cache[myKey] = 200Custom Structs
You can define your own compound data types using the struct keyword. A struct allows you to group multiple fields of different types together into a single cohesive unit.
type Person struct {
name String
age Number
isActive Boolean
}
# Instantiating the struct
let p = Person {
name: "John Doe",
age: 30,
isActive: true
}
# Accessing properties
let currentAge = p.ageNullable Types and Safe Navigation
In Cajá, arrays, maps, and custom structs can be made explicitly nullable by appending a ? to the type name. This signals to the compiler that the variable can hold either a valid instance of the type or nil.
# A nullable custom struct
let s: Person? = nil
# A nullable array
let arr: [String]? = nil
# A nullable map
let m: map[String]Number? = nilThe Safe Navigation Operator (?.)
To guarantee memory safety at compile time and permanently eliminate null pointer exceptions at runtime, Cajá requires the use of the safe navigation operator (?.) when accessing properties of any nullable type.
If the value is nil, the expression immediately short-circuits and evaluates to nil rather than throwing an error. This is especially powerful when cascading property accesses through deeply nested structures.
type Node struct {
val Number
next Node?
}
let n = Node { val: 42, next: nil }
# Reassigning 'next' to another node
n.next = Node { val: 100, next: nil }
# Safely accessing a property from a nullable type
let nextVal = n.next?.val
# Cascading safe navigation through deeply nested nullable properties
let deeplyNestedVal = n.next?.next?.next?.val
if (deeplyNestedVal != nil) {
# Safe to proceed
}