Variables & Data Types
Flowa is a dynamically-typed language where variables can hold any type and change at runtime.
Variable Declaration
All variables are declared with the let keyword:
let name = "Alice";
let age = 30;
let pi = 3.14159;
let active = true;
let data = null;Variable Rules
- Must start with a letter or underscore
- Can contain letters, digits, underscores
- Case-sensitive (
myVar≠myvar) - Cannot use reserved keywords
Reserved Keywords
let, func, if, else, while, for, return, true, false, null, break, continue, import, exportData Types
Strings
Strings are sequences of characters enclosed in double quotes:
let greeting = "Hello, World!";
let multiline = "Line 1
Line 2
Line 3";
let empty = "";String Operations
// Concatenation
let first = "Hello";
let last = "World";
let combined = first + " " + last; // "Hello World"
// Length
let length = len("Hello"); // 5
// Case conversion
let upper_str = upper("hello"); // "HELLO"
let lower_str = lower("WORLD"); // "world"
// Substring extraction
let str = "Hello, World!";
let sub = substring(str, 0, 5); // "Hello"
// Contains check
let has_world = contains(str, "World"); // true
// Trim whitespace
let trimmed = trim(" hello "); // "hello"
// Check prefix/suffix
let starts = startsWith("Hello", "He"); // true
let ends = endsWith("Hello", "lo"); // true
// Get character at index
let char = charAt("Hello", 1); // "e"
// Replace
let replaced = replace("Hello World", "World", "Flowa"); // "Hello Flowa"
// Split
let parts = split("a,b,c", ","); // ["a", "b", "c"]Numbers
Flowa supports both integers and floating-point numbers:
let integer = 42;
let negative = -10;
let float_num = 3.14159;
let scientific = 1.5e10;Arithmetic Operations
let a = 10;
let b = 3;
let add = a + b; // 13
let sub = a - b; // 7
let mul = a * b; // 30
let div = a / b; // 3.333...
let mod = a % b; // 1 (modulo/remainder)Math funcs
// Power
let pow_result = power(2, 8); // 256
// Square root
let sqrt_val = sqrt(16); // 4
// Rounding
let floor_val = floor(3.7); // 3
let ceil_val = ceil(3.2); // 4
let round_val = round(3.5); // 4
// Absolute value
let abs_val = abs(-5); // 5
// Min/Max
let min_val = min(10, 5); // 5
let max_val = max(10, 5); // 10Booleans
Boolean values represent true or false:
let is_active = true;
let is_completed = false;Boolean Operations
let x = true;
let y = false;
// Logical AND
let and_result = x && y; // false
// Logical OR
let or_result = x || y; // true
// Logical NOT
let not_result = !x; // falseComparison Operators
let a = 5;
let b = 10;
let eq = a == b; // false (equal)
let neq = a != b; // true (not equal)
let lt = a < b; // true (less than)
let lte = a <= b; // true (less than or equal)
let gt = a > b; // false (greater than)
let gte = a >= b; // false (greater than or equal)Null
null represents the absence of a value:
let empty_value = null;
if (empty_value == null) {
print("Value is null");
}Arrays
Arrays are ordered collections of values:
// Empty array
let arr = [];
// Array with values
let numbers = [1, 2, 3, 4, 5];
// Mixed types
let mixed = [1, "two", 3.0, true, null];Array Access
let numbers = [10, 20, 30, 40, 50];
// Access by index (0-based)
let first = numbers[0]; // 10
let third = numbers[2]; // 30
// Modify elements
numbers[1] = 25; // [10, 25, 30, 40, 50]Array Operations
let arr = [1, 2, 3];
// Add element to end
arr = push(arr, 4); // [1, 2, 3, 4]
// Remove last element
let last = pop(arr); // 4, arr = [1, 2, 3]
// Remove first element
let first = shift(arr); // 1, arr = [2, 3]
// Reverse array
let reversed = reverse([1, 2, 3]); // [3, 2, 1]
// Sort array
let sorted = sort([3, 1, 4, 1, 5]); // [1, 1, 3, 4, 5]
// Slice (extract portion)
let numbers = [1, 2, 3, 4, 5];
let subset = slice(numbers, 1, 3); // [2, 3]
// Check if includes value
let has_three = includes([1, 2, 3], 3); // true
// Find index of value
let idx = indexOf([1, 2, 3, 2], 2); // 1 (first occurrence)
// Get length
let length = len(arr);
// Join array
let joined = join(["a", "b", "c"], "-"); // "a-b-c"Hashes (Objects/Dictionaries)
Hashes store key-value pairs:
// Empty hash
let hash = {};
// Hash with values
let person = {
"name": "Alice",
"age": 30,
"city": "New York"
};Important: Always use quoted strings for hash keys.
Hash Access
let person = {
"name": "Bob",
"age": 25,
"email": "bob@example.com"
};
// Access values
let name = person["name"]; // "Bob"
let age = person["age"]; // 25
// Modify values
person["age"] = 26;
// Add new keys
person["phone"] = "555-1234";Hash Operations
let user = {
"name": "Bob",
"age": 25,
"email": "bob@example.com"
};
// Check if key exists using 'in' operator
if ("name" in user) {
print("User has a name");
}
// Get all keys
let keys = keys(user); // ["name", "age", "email"]
// Get all values
let values = values(user); // ["Bob", 25, "bob@example.com"]Nested Hashes
let user = {
"name": "Alice",
"address": {
"street": "123 Main St",
"city": "Boston",
"zip": "02101"
},
"contacts": {
"email": "alice@example.com",
"phone": "555-5678"
}
};
// Access nested values
let city = user["address"]["city"]; // "Boston"
let email = user["contacts"]["email"]; // "alice@example.com"Type Conversion
To Number
let str = "42";
let num = tonumber(str); // 42
let invalid = tonumber("abc"); // Returns null or 0To String
let num = 42;
let str = tostring(num); // "42"
let bool = true;
let str2 = tostring(bool); // "true"Type Checking
let value = "hello";
let type_name = type(value); // "string"
// Possible return values:
// "string", "number", "boolean", "array", "hash", "func", "null"
if (type(value) == "string") {
print("It's a string!");
}Variable Scope
Global Scope
Variables declared outside funcs are global:
let global_var = "I'm global";
func test() {
print(global_var); // Can access global
}
test();Local Scope
Variables declared inside funcs are local:
func test_scope() {
let local_var = "I'm local";
print(local_var);
}
test_scope();
// print(local_var); // ERROR - out of scopeClosure
funcs can capture variables from outer scopes:
func create_counter() {
let count = 0;
func increment() {
count = count + 1;
return count;
}
return increment;
}
let counter = create_counter();
print(counter()); // 1
print(counter()); // 2
print(counter()); // 3Best Practices
Meaningful Names
// Good
let user_count = 10;
let is_active = true;
let total_price = 99.99;
// Avoid
let x = 10;
let flag = true;
let temp = 99.99;Initialize Variables
// Good
let count = 0;
let items = [];
let user = {};
// Avoid uninitialized variables
let data; // undefined behaviorUse Appropriate Types
// Use arrays for collections
let numbers = [1, 2, 3, 4, 5];
// Use hashes for structured data
let user = {
"id": 123,
"name": "Alice",
"email": "alice@example.com"
};
// Use null for absent values
let optional_value = null;Examples
Working with User Data
let user = {
"id": 1,
"username": "alice",
"email": "alice@example.com",
"age": 30,
"is_active": true,
"tags": ["developer", "admin"],
"preferences": {
"theme": "dark",
"language": "en"
}
};
// Access and modify
print("User: " + user["username"]);
user["age"] = user["age"] + 1;
user["tags"] = push(user["tags"], "moderator");
// Type checking
if (type(user["tags"]) == "array") {
print("Tags count: " + tostring(len(user["tags"])));
}Data Processing
let prices = [19.99, 29.99, 39.99, 49.99];
let total = 0;
let i = 0;
while (i < len(prices)) {
total = total + prices[i];
i = i + 1;
}
print("Total: $" + tostring(total));
print("Average: $" + tostring(total / len(prices)));Next Steps
- Control Flow - Learn about if/else, loops, and more
- funcs - Explore funcs and closures
- Control Flow - Learn about if/else, loops, and more
- funcs - Explore funcs and closures