Constants
Constants provide named values that are known at compile time or cannot change during program execution. This guide covers module-level constants and const functions.
Module-Level Constants
Constants defined at the module level must use $ (immutable binding):
let $MAX_CONNECTIONS = 100;
let $DEFAULT_TIMEOUT = 30s;
let $API_BASE_URL = "https://api.example.com";
let $SUPPORTED_FORMATS = ["json", "xml", "csv"];
Why $ is Required
Module-level bindings are shared across the program. Making them immutable prevents one module from changing a value and breaking another:
// This would be dangerous if allowed
let shared_counter = 0; // ERROR: module-level bindings must be immutable
shared_counter = 1; // Could break other modules
// This is safe
let $shared_value = 42; // Cannot be changed
Public Constants
Export constants with pub:
pub let $MAX_RETRIES = 3;
pub let $API_VERSION = "v2";
// Private constant (default)
let $INTERNAL_BUFFER_SIZE = 1024;
Referencing Constants
Constants can reference other constants:
let $BASE_TIMEOUT = 10s;
let $EXTENDED_TIMEOUT = $BASE_TIMEOUT * 3; // 30s
let $MAX_TIMEOUT = $EXTENDED_TIMEOUT * 2; // 60s
let $API_VERSION = "v2";
let $API_BASE = "https://api.example.com";
let $API_URL = `{$API_BASE}/{$API_VERSION}`; // Full URL
Reference Order
Constants must be defined before they’re used:
// OK: $A is defined before $B
let $A = 10;
let $B = $A * 2;
// ERROR: $Y used before definition
let $X = $Y * 2; // $Y doesn't exist yet
let $Y = 10;
Importing Constants
Import constants with their $ prefix:
use "./config" { $MAX_CONNECTIONS, $DEFAULT_TIMEOUT };
use "./api" { $API_URL, $API_VERSION };
@make_request () -> Result<Response, Error> uses Http =
Http.get(url: $API_URL, timeout: $DEFAULT_TIMEOUT);
Aliasing Constants
use "./config" { $MAX_CONNECTIONS as $MAX_CONN };
@check_capacity (current: int) -> bool =
current < $MAX_CONN;
Const Functions
For computed constants, use const functions:
let $square = (x: int) -> int = x * x;
let $double = (x: int) -> int = x * 2;
Recursive Const Functions
Const functions can be recursive:
let $factorial = (n: int) -> int =
if n <= 1 then 1 else n * $factorial(n: n - 1);
let $fibonacci = (n: int) -> int =
if n <= 1 then n else $fibonacci(n: n - 1) + $fibonacci(n: n - 2);
Using Const Functions
When called with constant arguments, they’re evaluated at compile time:
// Computed at compile time
let $GRID_SIZE = $square(x: 10); // 100
let $PERMUTATIONS = $factorial(n: 5); // 120
let $FIB_10 = $fibonacci(n: 10); // 55
When called with runtime arguments, they’re evaluated at runtime:
@compute (n: int) -> int = $square(x: n); // Evaluated at runtime
Const Function Restrictions
Const functions must be pure — they cannot:
- Use capabilities (
uses Http, etc.) - Perform I/O
- Access mutable state
- Call non-const functions
// OK: pure computation
let $add = (a: int, b: int) -> int = a + b;
// ERROR: uses capability
let $fetch = (url: str) -> str uses Http = Http.get(url: url);
// ERROR: calls non-const function
let $random_add = (a: int) -> int = a + get_random();
Constant Expressions
Supported Operations
Constants support:
// Arithmetic
let $SUM = 10 + 20;
let $PRODUCT = 5 * 6;
let $QUOTIENT = 100 / 4;
// String operations
let $GREETING = "Hello, " + "World!";
let $FORMATTED = `Value: {$SUM}`;
// Collections
let $ITEMS = [1, 2, 3];
let $CONFIG = {"key": "value"};
// Const function calls
let $SQUARED = $square(x: 5);
Compile-Time Evaluation
The compiler evaluates constant expressions where possible:
let $A = 10;
let $B = 20;
let $C = $A + $B; // Compiler computes: 30
// Used in code as literal 30
@example () -> int = $C;
Configuration Patterns
Application Configuration
// config.ori
pub let $ENV = "production";
pub let $DATABASE_URL = match $ENV {
"production" -> "postgres://prod.db:5432/app"
"staging" -> "postgres://staging.db:5432/app"
_ -> "postgres://localhost:5432/app_dev"
};
pub let $LOG_LEVEL = match $ENV {
"production" -> "warn"
"staging" -> "info"
_ -> "debug"
};
Feature Flags
pub let $FEATURES = {
"new_ui": true,
"beta_api": false,
"analytics": true,
};
@is_enabled (feature: str) -> bool =
$FEATURES[feature] ?? false;
@test_features tests @is_enabled () -> void = {
assert(condition: is_enabled(feature: "new_ui"));
assert(condition: !is_enabled(feature: "beta_api"));
assert(condition: !is_enabled(feature: "unknown"))
}
Size and Time Constants
pub let $MAX_FILE_SIZE = 10mb;
pub let $REQUEST_TIMEOUT = 30s;
pub let $RETRY_DELAY = 100ms;
pub let $SESSION_DURATION = 2h;
pub let $BUFFER_SIZE = 4kb;
pub let $CACHE_LIMIT = 100mb;
Complete Example
// constants.ori - Application constants
// API Configuration
pub let $API_VERSION = "v2";
pub let $API_HOST = "api.example.com";
pub let $API_BASE_URL = `https://{$API_HOST}/{$API_VERSION}`;
// Limits
pub let $MAX_PAGE_SIZE = 100;
pub let $DEFAULT_PAGE_SIZE = 20;
pub let $MAX_RETRIES = 3;
// Timeouts
pub let $CONNECTION_TIMEOUT = 10s;
pub let $REQUEST_TIMEOUT = 30s;
pub let $LONG_POLL_TIMEOUT = 5m;
// Computed constants
let $calculate_backoff = (attempt: int) -> Duration =
if attempt <= 0 then 100ms
else 100ms * $power(base: 2, exp: attempt);
let $power = (base: int, exp: int) -> int =
if exp <= 0 then 1 else base * $power(base: base, exp: exp - 1);
pub let $RETRY_BACKOFFS = [
$calculate_backoff(attempt: 0), // 100ms
$calculate_backoff(attempt: 1), // 200ms
$calculate_backoff(attempt: 2), // 400ms
];
// Validation
pub let $MIN_PASSWORD_LENGTH = 8;
pub let $MAX_USERNAME_LENGTH = 50;
pub let $ALLOWED_EXTENSIONS = ["jpg", "png", "gif", "webp"];
// Feature flags
pub let $ENABLE_CACHING = true;
pub let $ENABLE_COMPRESSION = true;
pub let $ENABLE_RATE_LIMITING = true;
// usage.ori - Using the constants
use "./constants" {
$API_BASE_URL,
$REQUEST_TIMEOUT,
$MAX_RETRIES,
$RETRY_BACKOFFS,
$ENABLE_CACHING,
};
@fetch_data (endpoint: str) -> Result<str, Error> uses Http, Cache = {
let url = `{$API_BASE_URL}/{endpoint}`;
// Check cache if enabled
if $ENABLE_CACHING then {
let cached = Cache.get(key: url);
if is_some(option: cached) then return Ok(cached.unwrap_or(default: ""))
};
// Fetch with retries
let result = fetch_with_retry(
url: url
timeout: $REQUEST_TIMEOUT
max_retries: $MAX_RETRIES
backoffs: $RETRY_BACKOFFS
);
// Cache successful result
if is_ok(result: result) && $ENABLE_CACHING then
match result { Ok(data) -> Cache.set(key: url, value: data, ttl: 5m), Err(_) -> ()};
result
}
@fetch_with_retry (
url: str,
timeout: Duration,
max_retries: int,
backoffs: [Duration],
) -> Result<str, Error> uses Http = {
let attempt = 0;
loop {
let result = Http.get(url: url, timeout: timeout);
if is_ok(result: result) then break result;
if attempt >= max_retries then break result;
let delay = backoffs[attempt] ?? 1s;
sleep(duration: delay);
attempt = attempt + 1
}
}
// Placeholder
@sleep (duration: Duration) -> void = ();
@test_fetch tests @fetch_data () -> void =
with Http = MockHttp { responses: {} },
Cache = MockCache {} in {
// Test would go here
()
}
Quick Reference
Module-Level Constants
let $NAME = value; // Private constant
pub let $NAME = value; // Public constant
Const Functions
let $fn_name = (param: Type) -> ReturnType = expression;
Importing Constants
use "./module" { $CONSTANT };
use "./module" { $CONSTANT as $ALIAS };
Common Patterns
// Computed from other constants
let $DERIVED = $BASE * 2;
// Conditional based on environment
let $VALUE = match $ENV { "prod" -> x, _ -> y};
// Collection constants
let $ITEMS = [a, b, c];
let $CONFIG = {"key": value};
What’s Next
Now that you understand constants:
- Testing — Comprehensive testing strategies
- Capabilities — Explicit effects and testing