[m-users.] Is there a way to make io functions throw an exception, instead of returning io.res

Peter Wang novalazy at gmail.com
Sat Mar 30 12:14:07 AEDT 2019


Hi,

On Fri, 29 Mar 2019 11:18:31 -0500, Charles Shuller <charles.shuller at gmail.com> wrote:
> For my current project, I will never attempt to recover from an error, and
> just want to fail reporting the error.
> 
> Most io function return an io.res, or something closely related, which
> needs checking instead of throwing an exception.   And I get a LOT of
> repetitive, error handling code cluttering up my predicate bodies.
> 
> Is there some way I can box those functions up to throw an exception on
> error, instead?   Most of my code looks a lot like:
> 
> remove_file_recursively(Path, !IO) :-
>   io.remove_file_recursively(Path, Res, !IO),
>   (
>     Res = ok
>   ;
>     Res = error(Error),
>     io.error_message(Error, ErrorString),
>     string.format("Could not recursively remove %s: %s", [s(Path),
> s(ErrorString)], ExceptionMessage),
>     exception.throw(ExceptionMessage)
>   ).
> 
> With only minor variations for the position of Res in the io function call,
> and the actual Result type (io.res, io.res(T), io.result, etc.....).   So
> it SEEMS like it might be possible to write a predicate like:
> io_det(io.remove_file_recursively,
> Path, !IO)

You could write a higher-order predicate with type and mode:

    :- pred throw_on_error(pred(io.res, io, io), io, io).
    :- mode throw_on_error(in(pred(out, di, uo) is det), di, uo) is det.

Or, you can simply call a predicate that throws an exception if the
input argument is not ok.

    :- pred throw_on_error(io.res::in) is det.

    throw_on_error(Res) :-
        (
            Res = ok
        ;
            Res = error(Error),
            throw(Error)
        ).

Peter


More information about the users mailing list