[erlang-questions] Nested Case Statements v.s. multiple functions
Nathaniel Waisbrot
nathaniel@REDACTED
Mon Sep 25 16:20:03 CEST 2017
More functions is almost always better. You are writing in a functional language. :) I lean towards naming the functions for what they'll do, rather than having an initial arg that tells them what to do: `do_something(Arg)` rather than `do(something, Arg)`.
In your code, it looks like you have a success-path and anything that deviates is an error (a serious one?). I'd begin by writing it:
```
send_update(Request) ->
{ok, IndexArgs} = check_request(Request),
{ok, IndexResult} = check_indices(IndexArgs)
{ok, ValueResult} = get_values(IndexResult)
ok = transmit(ValueResult).
```
Here, we have a clear description of the happy-path and anything else will crash. If this is a server handling single-shot client requests (a REST server, for example) then you can either silently drop bad clients or have a top-level exception handler that just returns a 4xx or 5xx error. That may be enough right there, but even if you want richer responses to your clients I think the happy-path is a great way to start. The other thing it will do is help you start to think about overall resilience: it's cool if you drop one TCP connection because of an unexpected request, but all your other live connections and the rest of the system ought to be unaffected.
> On Sep 25, 2017, at 9:25 AM, code wiget <codewiget95@REDACTED> wrote:
>
> Hello everyone,
>
> As I get further into Erlang, I am starting to realize that some of my functions have been getting pretty ugly with nested case statements. For example, I had a nested case statement that looked something like this:
>
> Send_update(Arg1) ->
> case do this(Arg1) of
> {ok, [Val1, Val2]} ->
> case do_that(Val1, Val2) of
> {ok, [Val3, Val4]} ->
> case do_this2(…) of
> ….
>
> It continued into this for another few functions, you get the picture - its ugly, and it is hard to read.
>
> So I went and I converted it to a top level function that would then call lower level functions like so:
>
>
>
> send_update(Arg1) ->
> case ... of
> {ok, [Val1, Val2]} ->
> send_update(check_indices, {Arg1, Val1, Val2});
> Else ->
> lager:error("ERROR: ..")
> end.
> send_update(check_indices, {Arg1, Arg2, Arg3}) ->
> case check_indices(Arg2, Arg3)of
> true ->
> send_update(get_values, {Arg1, Arg3});
> false ->
> lager:error("EMERGENCY: ….")
> end;
> send_update(get_values, {Arg1, Arg2}) ->
> ...
> case ... of
> {ok, [Val1, Val2, VAl3]} ->
> send_update(send_value, {Arg1, Val1, Val2, Val3});
> Error ->
> lager:error("ERROR: …")
> end;
> send_update(send_value, {Arg1, Arg2, Arg3, Arg4}) ->
> …
> Do_something(Args),
> ok.
>
>
> Now that I look at it though, both don’t look right. They don’t look like something I would write in any other language where I would just have if’s and else’s.
>
> Is this the proper way to write Erlang? I know everyone has their own style, but I assume there is some accepted form of writing functional programs with deep nests.
>
> Thank you for your advice!
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
More information about the erlang-questions
mailing list