Variables and scope are fundamental to programming. Topaz provides a modern and safe variable system that reduces bugs and increases code clarity. 🎯
🔧 Variable Declaration
let - Immutable Variables (Default)
// All variables are immutable by default
let name = "John Topaz"
let age = 25
let isActive = true
// Cannot be changed once defined
// name = "Different Name" // Compile error!
let mut - Mutable Variables
// Use let mut when you need to change values
let mut score = 100
let mut message = "Initial message"
// Value can be changed
score = 95
message = "Updated message"
print("Current score: {score}") // "Current score: 95"
const - Compile-time Constants
// Constants determined at compile time
const MAX_SIZE: int = 1000
const APP_NAME: string = "Topaz Calculator"
const PI: float = 3.141592653589793
// Global constants available in other files
const defaultConfig = {
language: "English",
theme: "dark",
autoSave: true
}
🎯 Type Inference and Explicit Types
// Type inference (recommended)
let inferredNumber = 42 // int
let inferredString = "Hello" // string
let inferredArray = [1, 2, 3] // [int]
// Explicit types (when needed)
let explicitNumber: int = 42
let explicitString: string = "Hello"
let explicitArray: [int] = [1, 2, 3]
// Explicit types help with complex cases
let userData: { name: string, age: int } = {
name: "Developer Kim",
age: 30
}
🏠 Scope Rules
Global Scope
// File top level - global scope
let globalVariable = "Accessible everywhere"
const globalConstant = 100
function useAnywhere() {
print(globalVariable) // Accessible
print(globalConstant) // Accessible
}
Function Scope
function calculator(a: int, b: int) -> int {
// Function parameters also belong to function scope
let result = a + b // Function scope
let mut tempValue = a * 2 // Function scope
print("Result: {result}")
return result
}
// print(result) // Error! Cannot access outside function
Block Scope
function scopeExample() {
let outerVariable = "outside"
if true {
let innerVariable = "inside" // Block scope
let mut blockMutable = 10 // Block scope
print(outerVariable) // Accessible (outer scope)
print(innerVariable) // Accessible (same scope)
}
print(outerVariable) // Accessible
// print(innerVariable) // Error! Cannot access outside block
}
Loop Scope
// for loop variables have loop scope
for i in 0..5 {
let loopVariable = i * 2
print("i: {i}, value: {loopVariable}")
}
// print(i) // Error! Cannot access outside loop
// while loops work the same way
let mut counter = 0
while counter < 3 {
let temp = counter + 10
print(temp)
counter += 1
}
🔒 Variable Shadowing
let name = "John Topaz"
function shadowingExample() {
let name = "Developer Park" // Shadows global name
print("In function: {name}") // "In function: Developer Park"
{
let name = "Designer Lee" // Shadows function name
print("In block: {name}") // "In block: Designer Lee"
}
print("After block: {name}") // "After block: Developer Park"
}
print("Global: {name}") // "Global: John Topaz"
shadowingExample()
🌟 Closures and Scope
function createCounter(initialValue: int) -> function() -> int {
let mut count = initialValue // Captured by closure
return function() -> int {
count += 1 // Access outer scope variable
return count
}
}
let counter1 = createCounter(0)
let counter2 = createCounter(100)
print(counter1()) // 1
print(counter1()) // 2
print(counter2()) // 101
print(counter1()) // 3
🎭 Pattern Matching and Variables
let user = {
name: "John Topaz",
age: 28,
job: "Developer"
}
// Destructuring creates new variables
let { name, age } = user
print("Name: {name}, Age: {age}")
// Variable binding in match
match user.age {
case age if age < 20 => print("Likely a student")
case age if age < 30 => print("Young professional")
case age => print("Experienced: {age} years old")
}
// Array pattern matching
let scores = [95, 87, 92, 88]
match scores {
case [first, second, ...rest] => {
print("First: {first}")
print("Second: {second}")
print("Rest: {rest}")
}
}
⚡ Advanced Scope Patterns
IIFE (Immediately Invoked Function Expression)
// Immediately invoked function for scope isolation
let result = (function() -> int {
let tempCalculation = 10 * 20
let adjustment = 50
return tempCalculation + adjustment
})()
print(result) // 250
// tempCalculation, adjustment are not accessible
Module Scope
// math_utils.tpz file
export const PI = 3.141592653589793
export let defaultPrecision = 6
export function circleArea(radius: float) -> float {
let internalCalc = radius * radius // Only accessible within module
return PI * internalCalc
}
// main.tpz file
import { PI, circleArea } from "./math_utils"
print(PI) // Accessible
print(circleArea(5.0)) // Accessible
// print(internalCalc) // Error! Module internal variable not accessible
🛡️ Best Practices
1. Use Immutable by Default
// Good: Use let by default
let config = {
theme: "dark",
language: "English"
}
// Use let mut only when necessary
let mut progressStatus = "started"
progressStatus = "in-progress"
progressStatus = "completed"
2. Meaningful Variable Names
// Bad example
let a = userList.length()
let b = a * 0.1
// Good example
let totalUsers = userList.length()
let commission = totalUsers * 0.1
3. Minimize Scope
function processData(rawData: [int]) -> [int] {
let result = []
for item in rawData {
// Variables needed only in loop should be declared in loop
let transformedValue = item * 2 + 1
let validatedValue = if transformedValue > 0 { transformedValue } else { 0 }
result.push(validatedValue)
}
return result
}
🔍 Debugging Tips
// Utility for scope debugging
function printScopeInfo() {
let localVariable = "local"
print("Variables in current function:")
print("- localVariable: {localVariable}")
// Access global variables
if defined(globalVariable) {
print("- Global variable accessible")
}
}
// Check variable existence
function safeAccess(variableName: string) {
if defined(variableName) {
print("{variableName} is defined")
} else {
print("{variableName} is not defined")
}
}
Topaz's variable and scope system provides both safety and clarity. With immutability as default but allowing mutability when needed, and clear scope rules, you can write predictable code. 🚀