Re: How to handle nested case
"Richard O'Keefe" <[email protected]>
| Newsgroups | gmane.comp.lang.erlang.general |
|---|---|
| Message-ID | <CABcYAdLxraZjX5WmvPu04r2jh+18ZRBXaUW561TBZ1USWT8V2g@mail.gmail.com> |
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 <[email protected]> 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 <[email protected]> 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 >