How to handle nested case

Richard O'Keefe raoknz@REDACTED
Mon Sep 20 04:22:59 CEST 2021


It seems extremely likely that the code is not referentially
transparent to begin with.
That was meant as an *example* of try/catch, and the question of ambiguity was
addressed in that message of mine and in someone else's.

My *actual* recommendation is the higher-order combinator ok(f(), fun
(R) -> ... end), which I like precisely because it is
straightforwardly functional and adaptable.

On Mon, 20 Sept 2021 at 14:05, Michael Truog <mjtruog@REDACTED> wrote:
>
> If (try) catch is used that means the source code will not be
> referentially transparent (it will be impure) because any of the three
> functions may also throw.  That makes the approach an anti-pattern,
> something to avoid to promote code that easy to inline, optimize, test
> and understand.
>
>
> On 9/19/21 5:32 PM, Richard O'Keefe wrote:
> > What is wrong with 'try'?
> >
> > ok({ok,R}) -> R;
> > ok(E) -> throw(E).
> >
> >     try
> >        Server = ok(get_radius_host()),
> >        Port = ok(get_radius_port()),
> >        Secret = ok(get_radius_secret),
> >        {ok,{Server,Port,Secret}}
> >     catch throw:E ->
> >        E
> >     end
> >
> > WARNING: UNTESTED CODE.
> >
> > I'd be inclined to do something slightly different:
> >
> > ok({ok,R}, F) -> F(R);
> > ok(E) -> E.
> >
> >     ok(get_radius_server(), fun (Server) ->
> >     ok(get_radius_host(),    fun (Port) ->
> >     ok(get_radius_secret(), fun (Secret) ->
> >        {ok,{Server,Port,Secret}}
> >     end) end) end)
> >
> > (which is rather like using >>= \x -> rather than 'do' in Haskell).
> >
> > I would also be wondering whether it is possible for a non-OK result to be
> > ambiguous.  Are there values for E that could have come from more than
> > one of these 'get_*' functions?  Might the caller of your code care about
> > where the error came from?
> >
> > I find myself wondering whether a simple
> >     {ok,Server} = ...
> >     {ok,Port} = ....
> >     {ok,Secret} = ...
> > might not be the most idiomatic "let it crash" Erlang way of all.
> >
> > There is some important context missing here.
> > * Why isn't "let it crash" the right answer here?
> > * Why should the caller be told that an error occurred but
> >     in a possibly ambiguous way?
> > * Is there no other validation to be done?
> > * What do the surrounding comments say?
> >
> > On Sun, 19 Sept 2021 at 08:50, Gian Lorenzo Meocci <glmeocci@REDACTED> wrote:
> >> Hi,
> >> I have a function like this:
> >>
> >> get_nas_from_conf() ->
> >> case get_radius_host() of
> >> {ok, Server} ->
> >> case get_radius_port() of
> >> {ok, Port} ->
> >> case get_radius_secret() of
> >> {ok, Secret} ->
> >> {Server, Port, Secret};
> >> E -> E
> >> end;
> >> E ->
> >> E
> >> end;
> >> E ->
> >> E
> >> end.
> >>
> >> Which is the best way to write this kind of function?
> >>
> >> I'd like to have a with operator like in Elixir, to rewrite my function in this way:
> >>
> >> get_nas_from_conf() ->
> >> with {ok, Server} <- get_radius_host(),
> >> {ok, Port} = get_radius_port(),
> >> {ok, Secret} = get_radius_secret() ->
> >> {Server, Port, Secret};
> >> catch
> >> {error, _Reason} = E ->
> >> E
> >> end.
> >>
> >> Any suggestion?
> >>
> >> --
> >> GL
> >> https://www.meocci.it
>


More information about the erlang-questions mailing list