Manejo de errores: Resultado y Opcion
Forja adopta el patrón de Resultado para operaciones que pueden fallar, y Opcion para valores que pueden estar ausentes. Ambas son variantes de tipos algebraicos definidos en el preludio.
Opcion
Úsalo cuando un valor pueda ser Algun(valor) o Ninguno. Evita el uso de nulo y fuerza el manejo explícito del caso ausente.
tipo Opcion<T> = Algun(T) | Ninguno funcion primer_caracter(texto: Texto) → Opcion<Texto> {
si (texto == "") {
retornar Ninguno
}
retornar Algun(texto[0])
}
variable r = primer_caracter("forja")
coincidir (r) {
caso Algun(c) → escribir("Primer letra: " + c)
caso Ninguno → escribir("Vacío")
} Resultado
Úsalo para operaciones que pueden devolver Exito(valor) o Error(mensaje).
tipo Resultado<T, E> = Exito(T) | Error(E) funcion dividir(a: Entero, b: Entero) → Resultado<Entero, Texto> {
si (b == 0) {
retornar Error("División por cero")
}
retornar Exito(a / b)
}
variable r = dividir(10, 2)
coincidir (r) {
caso Exito(valor) → escribir("Resultado: " + valor)
caso Error(msg) → escribir("Error: " + msg)
} Keyword resultado en contratos
La keyword resultado se usa dentro de postcondiciones (asegura) para referirse al valor de retorno de una función. Es parte del sistema de Design by Contract de Forja:
funcion dividir(a: Entero, b: Entero) -> Entero
requiere b != 0
asegura resultado * b == a
{
retornar a / b
} resultado representa el valor de retorno.Keyword anterior — valor previo en postcondiciones
La keyword anterior captura el valor de una expresión antes de ejecutar la función. Se usa dentro de asegura para referirse al estado previo:
funcion incrementar(prestado mut x: Entero)
asegura x == anterior(x) + 1
{
x = x + 1
} anterior(x) guarda el valor de x al entrar a la función. La postcondición verifica que x incrementó exactamente en 1.
Keyword siempre — Invariante de clase
La keyword siempre define invariantes de clase: condiciones que deben cumplirse siempre, antes y después de cualquier método. Si un método deja la clase en un estado inválido, el invariante se rompe:
clase CuentaBancaria {
saldo
constructor(saldo_inicial) {
este.saldo = saldo_inicial
}
funcion depositar(prestado mut cantidad: Entero)
requiere cantidad > 0
asegura este.saldo == anterior(este.saldo) + cantidad
{
este.saldo = este.saldo + cantidad
}
// Invariante: el saldo nunca puede ser negativo
siempre este.saldo >= 0
} siempre se verifica al final de cada método de la clase. Si un método no lo cumple, se reporta un error en tiempo de ejecución.Tabla completa de Design by Contract
| Keyword | Dónde se usa | Descripción | Ejemplo |
|---|---|---|---|
requiere | Función / Método | Precondición: debe cumplirse antes de ejecutar | requiere b != 0 |
asegura | Función / Método | Postcondición: se verifica después de ejecutar | asegura resultado * b == a |
resultado | Postcondición (asegura) | Representa el valor de retorno de la función | asegura resultado > 0 |
anterior | Postcondición (asegura) | Captura el valor de una expresión antes de ejecutar | asegura x == anterior(x) + 1 |
siempre | Clase | Invariante: condición que se cumple siempre en toda instancia | siempre este.saldo >= 0 |
Alias útiles del preludio
| Tipo | Definición | Uso común |
|---|---|---|
Opcion<T> | Algun(T) | Ninguno | Valores ausentes |
Resultado<T, E> | Exito(T) | Error(E) | Operaciones fallibles |