Data Types¶
CacaoLang supports several core data types. Type inference means you don't need to explicitly declare types - the interpreter figures it out automatically.
Number¶
Numbers can be integers or floating-point values. There's no distinction between int and float at the language level.
let integer = 42;
let negative = -15;
let decimal = 3.14159;
let scientific = 2.5;
print typeof(integer); // number
print typeof(decimal); // number
Number Operations¶
let a = 10;
let b = 3;
print a + b; // 13 (addition)
print a - b; // 7 (subtraction)
print a * b; // 30 (multiplication)
print a / b; // 3.333... (division)
print a % b; // 1 (modulo)
String¶
Strings are sequences of characters enclosed in double quotes.
String Interpolation¶
Use #{} to embed expressions in strings:
let name = "Alice";
let age = 30;
let message = "My name is #{name} and I am #{age} years old";
print message; // My name is Alice and I am 30 years old
Escape Sequences¶
let newline = "Line 1\nLine 2";
let tab = "Column1\tColumn2";
let quote = "She said \"Hello\"";
let backslash = "Path: C:\\Users\\Name";
String Operations¶
let str1 = "Hello";
let str2 = "World";
// Concatenation
let combined = str1 + " " + str2;
print combined; // Hello World
// Length
print len(str1); // 5
// Indexing
print str1[0]; // H
print str1[4]; // o
// Case conversion
print uppercase(str1); // HELLO
print lowercase(str2); // world
Boolean¶
Boolean values represent true or false.
Boolean Operations¶
let a = true;
let b = false;
// Logical AND
print a && b; // false
// Logical OR
print a || b; // true
// Logical NOT
print !a; // false
print !b; // true
Truthiness¶
In conditional contexts:
- Truthy:
true, non-zero numbers, non-empty strings - Falsy:
false,0, empty strings ("")
Array¶
Arrays are ordered collections of values. They can contain mixed types.
let numbers = [1, 2, 3, 4, 5];
let strings = ["apple", "banana", "cherry"];
let mixed = [42, "hello", true, 3.14];
let nested = [[1, 2], [3, 4], [5, 6]];
print typeof(numbers); // array
Array Operations¶
let arr = [10, 20, 30, 40, 50];
// Access by index (0-based)
print arr[0]; // 10
print arr[2]; // 30
// Length
print len(arr); // 5
// Modify arrays (via functions)
arr = push(arr, 60);
print arr; // [10, 20, 30, 40, 50, 60]
let last = pop(arr);
print last; // 60
Array Iteration¶
Struct¶
Structs are user-defined composite types with named fields.
// Define a struct type
struct Person {
name,
age,
city
}
// Create an instance
let alice = Person {
name: "Alice",
age: 30,
city: "NYC"
};
print typeof(alice); // Person
// Access fields
print alice.name; // Alice
print alice.age; // 30
print alice.city; // NYC
Nested Structs¶
struct Address {
street,
city,
zip
}
struct Person {
name,
address
}
let addr = Address {
street: "123 Main St",
city: "Boston",
zip: "02101"
};
let person = Person {
name: "Bob",
address: addr
};
print person.address.city; // Boston
Lambda¶
Lambdas are anonymous functions that can be stored in variables and passed as arguments.
let double = |x| => { return x * 2; };
print typeof(double); // lambda
let result = double(5);
print result; // 10
Lambda with Multiple Parameters¶
See Lambdas for more details.
Nil¶
Nil represents the absence of a value. Variables don't start as nil by default, but nil can be used explicitly.
fn maybe_return(condition) {
if condition == true {
return 42;
}
// Implicitly returns nil
}
let result = maybe_return(false);
print typeof(result); // nil
Type Checking¶
Use typeof() to check the type of any value:
print typeof(42); // number
print typeof("hello"); // string
print typeof(true); // bool
print typeof([1, 2, 3]); // array
print typeof(|x| => {}); // lambda
Type Conversion¶
To String¶
To Number¶
let text = "123";
let num = int(text);
print num; // 123
let floatText = "3.14";
let decimal = float(floatText);
print decimal; // 3.14
Type Coercion¶
In Arithmetic¶
In Concatenation¶
// String concatenation requires both sides to be strings
let text = "Number: ";
let num = 42;
let combined = text + str(num);
print combined; // Number: 42
// Or use interpolation
let message = "Number: #{num}";
print message; // Number: 42
Summary¶
| Type | Example | Literal Syntax | Mutable |
|---|---|---|---|
| Number | 42, 3.14 |
Digits with optional decimal | Yes (via reassignment) |
| String | "hello" |
Double quotes | No (immutable) |
| Boolean | true, false |
Keywords | Yes (via reassignment) |
| Array | [1, 2, 3] |
Square brackets | Yes (via functions) |
| Struct | Person { ... } |
Struct literal | No (fields immutable) |
| Lambda | \|x\| => {} |
Pipe syntax | No |
| Nil | - | Implicit/explicit | - |
Best Practices¶
- Use descriptive variable names that indicate type
- Leverage type inference - don't worry about explicit types
- Check types with
typeof()when needed - Convert explicitly when mixing types
- Use structs for related data that belongs together