?? Okanran: Error Handling

Resilient code with proper error handling.

Use Case 1: Retry with Exponential Backoff

// retry.ifa - Retry failed operations with backoff

ise retry_with_backoff(operation, max_retries, initial_delay) {
    ayanmo attempt = 0;
    ayanmo delay = initial_delay;
    
    nigba (attempt < max_retries) {
        ayanmo result = Okanran.try(operation);
        
        ti (!Okanran.is_error(result)) {
            padap? result;  // Success!
        }
        
        ayanmo attempt = attempt + 1;
        
        ti (attempt < max_retries) {
            Irosu.fo("Attempt " + attempt + " failed, retrying in " + delay + "ms...");
            Oyeku.sleep(delay);
            ayanmo delay = delay * 2;  // Exponential backoff
        }
    }
    
    padap? Okanran.error("Max retries exceeded");
}

// Usage
ayanmo fetch_data = || {
    ayanmo response = Otura.get("https://api.example.com/data");
    ti (response["status"] != 200) {
        padap? Okanran.error("HTTP " + response["status"]);
    }
    padap? response["body"];
};

ayanmo result = retry_with_backoff(fetch_data, 3, 1000);

ti (Okanran.is_error(result)) {
    Irosu.kigbe("Failed after retries: " + Okanran.message(result));
} bib?k? {
    Irosu.fo("Success: " + result);
}

Use Case 2: Input Validation

// validation.ifa - Form validation with detailed errors

ise validate_email(email) {
    ti (Ika.len(email) == 0) {
        padap? Okanran.error("Email is required");
    }
    ti (!Ika.contains(email, "@")) {
        padap? Okanran.error("Email must contain @");
    }
    ti (!Ika.contains(email, ".")) {
        padap? Okanran.error("Email must contain domain");
    }
    padap? email;
}

ise validate_age(age) {
    ti (age == nil) {
        padap? Okanran.error("Age is required");
    }
    ti (Ogbe.type(age) != "number") {
        padap? Okanran.error("Age must be a number");
    }
    ti (age < 0 || age > 150) {
        padap? Okanran.error("Age must be between 0 and 150");
    }
    padap? age;
}

ise validate_user(data) {
    ayanmo errors = [];
    
    ayanmo email = validate_email(data["email"]);
    ti (Okanran.is_error(email)) {
        ayanmo errors = Ogunda.push(errors, {"field": "email", "message": Okanran.message(email)});
    }
    
    ayanmo age = validate_age(data["age"]);
    ti (Okanran.is_error(age)) {
        ayanmo errors = Ogunda.push(errors, {"field": "age", "message": Okanran.message(age)});
    }
    
    ti (Ogunda.len(errors) > 0) {
        padap? {"valid": iro, "errors": errors};
    }
    
    padap? {"valid": otito, "data": data};
}

// Usage
ayanmo input = {"email": "invalid", "age": -5};
ayanmo result = validate_user(input);

ti (!result["valid"]) {
    Irosu.fo("Validation failed:");
    fun err ninu result["errors"] {
        Irosu.fo("  " + err["field"] + ": " + err["message"]);
    }
} bib?k? {
    Irosu.fo("User is valid!");
}

Use Case 3: Safe File Operations

// safe_files.ifa - File operations with error handling

ise safe_read(path) {
    ti (!Odi.exists(path)) {
        padap? Okanran.error("File not found: " + path);
    }
    
    ayanmo result = Okanran.try(|| {
        padap? Odi.read(path);
    });
    
    ti (Okanran.is_error(result)) {
        padap? Okanran.error("Read failed: " + Okanran.message(result));
    }
    
    padap? result;
}

ise safe_write(path, content) {
    // Check directory exists
    ayanmo dir = Ika.rsplit(path, "/");
    ayanmo dir_path = Ogunda.first(dir);
    
    ti (Ika.len(dir_path) > 0 && !Odi.exists(dir_path)) {
        ayanmo mkdir_result = Okanran.try(|| {
            Odi.mkdir(dir_path);
        });
        
        ti (Okanran.is_error(mkdir_result)) {
            padap? Okanran.error("Cannot create directory: " + dir_path);
        }
    }
    
    ayanmo result = Okanran.try(|| {
        Odi.write(path, content);
    });
    
    ti (Okanran.is_error(result)) {
        padap? Okanran.error("Write failed: " + Okanran.message(result));
    }
    
    padap? otito;
}

ise safe_json_read(path) {
    ayanmo content = safe_read(path);
    ti (Okanran.is_error(content)) {
        padap? content;
    }
    
    ayanmo result = Okanran.try(|| {
        padap? Ogbe.parse_json(content);
    });
    
    ti (Okanran.is_error(result)) {
        padap? Okanran.error("Invalid JSON in " + path);
    }
    
    padap? result;
}

// Usage
ayanmo config = safe_json_read("config.json");
ti (Okanran.is_error(config)) {
    Irosu.fo("Using default config: " + Okanran.message(config));
    ayanmo config = {"default": otito};
} bib?k? {
    Irosu.fo("Config loaded successfully");
}

Use Case 4: Result Chain (Railway Pattern)

// railway.ifa - Chain operations that can fail

ise chain(value, operations) {
    ayanmo current = value;
    
    fun op ninu operations {
        ti (Okanran.is_error(current)) {
            padap? current;  // Short-circuit on error
        }
        ayanmo current = op(current);
    }
    
    padap? current;
}

// Processing pipeline
ise parse_user_input(input) {
    ti (input == nil || Ika.len(input) == 0) {
        padap? Okanran.error("Empty input");
    }
    padap? Ika.trim(input);
}

ise validate_format(data) {
    ti (!Ika.contains(data, ":")) {
        padap? Okanran.error("Invalid format, expected 'key:value'");
    }
    padap? Ika.split(data, ":");
}

ise transform_data(parts) {
    ti (Ogunda.len(parts) != 2) {
        padap? Okanran.error("Expected exactly 2 parts");
    }
    padap? {
        "key": Ogunda.first(parts),
        "value": Ogunda.last(parts)
    };
}

// Usage
ayanmo inputs = ["name:John", "invalid", "  age:25  ", ""];

fun input ninu inputs {
    ayanmo result = chain(input, [
        parse_user_input,
        validate_format,
        transform_data
    ]);
    
    Irosu.fo("Input: '" + input + "'");
    ti (Okanran.is_error(result)) {
        Irosu.fo("  ? " + Okanran.message(result));
    } bib?k? {
        Irosu.fo("  ? " + result["key"] + " = " + result["value"]);
    }
}