Nyx maneja los fallos de E/S en dos niveles. El primero devuelve Result<T, Error> y lo propaga con ?, así que quien llama decide qué hacer con el fallo; el segundo llama a unwrap() y muere en el acto, que es la opción honesta cuando no hay un fallback razonable. Esta receta usa try_read_file y try_write_file de std/fs junto con std/error.
// Errores tipados de E/S: Result<T, Error> cuando el caller reacciona, panic cuando morir es correcto import "std/fs" import "std/error" // Nivel 1 (Result): el caller de cargar_config puede reaccionar distinto // según el fallo, así que esta función NO decide por él — propaga el // Error con `?` sin necesitar saber por qué try_read_file falló. fn cargar_config(path: String) -> Result<String, Error> { let contenido: String = try_read_file(path)? return Result.Ok(contenido) } fn main() -> int { let path: String = "/tmp/nyx_example_101_config.txt" // Nivel 2 (panic): sembrar el archivo de ejemplo en /tmp. Si esto // falla, /tmp no es escribible y no hay fallback razonable — morir // acá con unwrap() es más honesto que seguir con un estado a medias. // Anotación explícita necesaria: un `let` sin tipo pierde el genérico // Result<T,E> (queda i8* opaco) y .unwrap() no dispatchea. let w: Result<int, Error> = try_write_file(path, "puerto=8080\nmodo=dev\n") w.unwrap() // Nivel 1: match exhaustivo, la config existe. match cargar_config(path) { Result.Ok(cfg) => { print(cfg) } Result.Err(e) => { print("no se pudo cargar config: " + error_to_string(e)) } } // Mismo Result, ahora el archivo no existe: el caller distingue el // tipo de fallo por e.kind sin parsear un string de mensaje. match cargar_config("/tmp/nyx_example_101_no_existe.txt") { Result.Ok(cfg) => { print(cfg) } Result.Err(e) => { print("kind: " + e.kind) } } return 0 }
puerto=8080 modo=dev kind: not_found
Cómo funciona
cargar_config es el primer nivel: try_read_file(path)? entrega el contenido del archivo o retorna temprano con el Error intacto. La función nunca necesita saber por qué falló la lectura — ? propaga el error tipado y Result.Ok(contenido) envuelve el caso de éxito.
Sembrar el archivo de ejemplo en /tmp es el segundo nivel. Si esa escritura falla, el directorio no es escribible y no hay un fallback sensato, así que w.unwrap() aborta. La anotación de let w: Result<int, Error> es obligatoria: un let sin tipo pierde los parámetros genéricos y .unwrap() deja de despachar.
Las dos llamadas a cargar_config se resuelven con match exhaustivo. La segunda pide un archivo que no existe, y la rama Result.Err lee e.kind — un campo del valor de error, no un mensaje que haya que parsear — y por eso la última línea de la salida es not_found.