Variables & Scope
A comprehensive guide to variable declaration, constants, and scope management in Dorpn's statically-typed environment.
Variable Declaration with tag
The tag keyword introduces mutable variables into the current scope. Variables declared with
tag can be reassigned new values, provided the new value matches the variable's inferred or
explicitly declared type.
- Mutability — values can be modified after initialization
- Type binding — each variable is permanently bound to a specific type (
Int,Float,String, orBool) - Scope awareness — variables exist from their point of declaration forward
- Case sensitivity — variable names follow standard identifier rules
Variables can be declared with explicit type annotations or rely on automatic type inference from the assigned value. The type, once established, remains fixed for the variable's lifetime.
tag name = "Dorpn" # String
tag count = 42 # Integer
tag price = 19.99 # Float
tag active = true # Boolean
Constants with Const
The Const keyword creates immutable named values that cannot be modified after initialization.
Constants provide compile-time guarantees about value stability and enable performance optimizations.
- Immutable by design — attempting to reassign a constant triggers a compile-time error
- Compile-time verification — constants are validated during compilation
- Naming convention — typically
UPPER_SNAKE_CASEfor clarity - Scope hierarchy — constants follow standard lexical scoping rules
Constants are ideal for configuration values, mathematical constants, application metadata, and any value that should remain invariant throughout program execution.
Const PI = 3.14159
Const APP_NAME = "Dorpn"
Const MAX_RETRIES = 3
Const PI = 3.14159
PI = 3.14 # ERROR: Cannot assign to constant!
Scope Rules & Visibility
Dorpn employs static (lexical) scoping where variable visibility is determined by the program's textual structure. Scopes are created by code blocks, function definitions, and control structures.
| Scope | Description |
|---|---|
| Global scope | Variables declared outside any function or block |
| Function scope | Variables declared within a function (local to that function) |
| Block scope | Variables declared within control structures (if, loop, keep
blocks) |
| Nested scopes | Inner scopes can access outer scope variables, but not vice versa |
Variables are available from their point of declaration:
tag global = "I'm available everywhere below"
if true:
tag local = "I'm only in this block"
print(global) # Works
print(local) # Works
print(global) # Works
# print(local) # ERROR: Not defined here
Shadowing behavior
A variable in an inner scope can "shadow" (temporarily hide) a variable with the same name from an outer scope. The original variable becomes inaccessible within the inner scope but regains visibility once the inner scope exits.
Lifetime management
- Variables exist from their point of declaration until the end of their containing scope
- Memory for variables is managed automatically via the generated C code
- No garbage collector overhead — memory is freed deterministically
Best Practices & Guidelines
Variable naming
- Use descriptive names that indicate purpose and content type
- Prefer
camelCasefor variables,UPPER_SNAKE_CASEfor constants - Avoid single-letter names except for loop counters or mathematical variables
- Consider type hints in names when beneficial (e.g.
userCount,priceFloat)
Declaration placement
- Declare variables as close as possible to their first use
- Group related variables with blank lines for visual separation
- Initialize variables at declaration when practical
- Place constants at the top of files or logical sections
Scope management
- Minimize variable scope to reduce cognitive load
- Avoid global variables when local alternatives exist
- Use constants for values that shouldn't change
- Consider function parameters over shared global state
| Aspect | tag Variables |
Const Constants |
|---|---|---|
| Mutability | Mutable (can be reassigned) | Immutable (fixed value) |
| Type flexibility | Fixed type after first assignment | Fixed type and value |
| Memory | May change memory allocation | Fixed allocation |
| Use case | Changing values, accumulators | Configuration, invariants |
| Naming convention | camelCase |
UPPER_SNAKE_CASE |
Common Pitfalls & Solutions
tag instead if the value needs to change.
Design Principles Behind Dorpn's Variable System
- Predictability over convenience — variables have fixed types to eliminate runtime type errors and enable better compiler optimizations
- Explicit over implicit — type inference is supported, but the system encourages clarity through appropriate naming and optional annotations
- Safety through immutability — constants provide compile-time guarantees about value stability, reducing bug surfaces
- Local reasoning — lexical scoping helps you understand variable visibility by examining local code structure
- Gradual disclosure — simple variable usage is straightforward; advanced patterns are available but not required for basic programs
