either & el ámbito Raise
Ejecuta un bloque en un ámbito Raise<E>: código en
línea recta que puede cortocircuitar con un error tipado. Un E
elevado se convierte en Left; un retorno normal, en
Right.
Lección
El constructor le entrega a tu bloque un ámbito r — el port
del either { } de Arrow en Kotlin. Todo cuelga de
él; escribe r. y descubre el vocabulario completo:
r.bind(either)/r.bindAll(eithers)— desenvuelve un acierto o cortocircuita con el fallo.r.ensure(cond, () => err)— elrequirede los errores tipados.r.ensureNotNull(x, () => err)— devuelve un valor no nulo, con promoción de tipo.r.recover(block, onRaise)— trata un error elevado en un ámbito anidado y sigue adelante.r.withError(transform, block)— adapta un tipo de error distinto a este ámbito.r.raise(err)— cortocircuita directamente; devuelveNever, así que el análisis de flujo sabe que la ejecución se detiene.
Por dentro esto no es un encadenamiento de flatMap:
un bind fallido lanza una señal privada, etiquetada con el
ámbito, que el constructor captura en su frontera. Por eso los retornos
tempranos, los bucles y los if funcionan sin más dentro del
bloque, y por eso los constructores anidados nunca capturan los errores de
los demás. eitherAsync es el gemelo asíncrono — mismo
vocabulario, con await permitido (elevar errores solo dentro
de la misma cadena de awaits).
Demo 1 · ensure & ensureNotNull
Demo 2 · bind — el asesino de la pirámide de flatMap
Demo 3 · recover, withError & raise
Demo 4 · eitherCatching — la frontera de excepciones, precombinada
El parseo real falla por dos vías a la vez: tus reglas
lanzan con raise errores tipados, mientras la plataforma
(int.parse, jsonDecode) lanza
excepciones. eitherCatching es either +
catching en un solo builder — el bloque puede hacer raise
o lanzar, y el segundo argumento convierte cualquier excepción lanzada
en el mismo error tipado. La señal de raise nunca se le entrega.
recover acepta la misma cláusula opcional
onThrow:, completando el recover(block, recover,
catch) de tres cláusulas de Arrow 2.x.
Pruébalo tú
Ejercicio: haz que checkAge falle con un error tipado en vez
de lanzar una excepción — ensureNotNull para el parseo,
ensure para el límite de edad.
toList() dentro, o usa los
terminales ansiosos de Either; un raise
diferido falla ruidosamente con RaiseLeakedError. (2) Nunca
uses un catch pelado dentro de un bloque raise — usa
catching/catchingAsync, que siempre dejan pasar
la señal de cortocircuito.
Either — el tipo frontera ·
nullable — el gemelo sin información que devuelve T? ·
acumulación — recoge todos los fallos ·
errores tipados — guía completa