Exception
Exceções são somente um tipo especial variante, "lançadas" em casos excepcionais (não abuse delas!).
Uso
let getItem = (theList) =>
if (callSomeFunctionThatThrows()) {
/* return the found item here */
} else {
raise(Not_found)
};
let result =
try (getItem([1, 2, 3])) {
| Not_found => 0 /* Default value if getItem throws */
};
Note que o trecho acima é somente para demonstração; o mais correto é você retornar um option(int)
diretamente de getItem
e evitar o try
completamente.
Você pode casar expressões com exceções diretamente enquanto espera outro valor retornado por uma função:
switch (List.find((i) => i === oItem, meusItems)) {
| item => print_endline(item)
| exception Not_found => print_endline("O item não foi encontrado!")
};
Você pode também criar suas próprias exceções tal como você criaria um variant (exceções também devem iniciar com letra maiúscula).
exception EntradaFechada(string);
...
raise(EntradaFechada("o stream de entrada foi fechado!"));
Dicas & Truques
Quando você tiver variantes usuais, você geralmente não precisa de exceções. Por exemplo, ao invés de lançar uma exceção quando um item
não pode ser encontrado, tente retornar um option(item)
(None
neste caso).
Decisões de Design
A dica acima parece contradizer o que acontece na biblioteca padrão OCaml; funções proeminentes em módulos como List e String parecem lançar exceções excessivamente. Isto é parcialmente devido a decisões antigas; e parcialmente devido ao cuidado extremo em prover performance. OCaml/Reason nativo é extremamente performático; lançamento de exceções foi projetado para ser muito barato em termo de recursos, mais barato que alocar e retornar e.g. um option
. Infelizmente, esse não é o caso de JavaScript.
Novas alternativas para a biblioteca padrão normalmente vêm com funções que retornam option
ao invés de lançar exceções. Por examplo, List.find
possui uma alternativa que retorna option
, List.find_opt
, que não lança exceções.
Exceções são na verdade variantes também. De fato, todos pertencem a único tipo variante, chamado exn
. É uma variante extensível, o que significa que você pode adicionar novos construtores, como InputClosed
acima. exception Foo
é somente açúcar sintático para adicionar um construtor a exn
.