[erlang-questions] Nested Case Statements v.s. multiple functions

Gleb Vinogradov g.a.vinogradov@REDACTED
Tue Sep 26 07:20:00 CEST 2017


Well, this example could be easily written with Erlang _if_ operator:

muldiv(First, Second) ->
    if
        not is_integer(First) -> {error, "First must be an integer"};
        not is_integer(Second) -> {error, "Second must be an integer"};
        Second =:= 0 ->  {error, "Second must not be zero!"};
        true ->
            Quotient = First div Second,
            Product = First * Second,
            {ok, {Product, Quotient}}
    end.



2017-09-26 9:40 GMT+07:00 dploop@REDACTED <dploop@REDACTED>:

> This problem also bothered me for a long time, so I write a parse
> transform to deal with it. To be specific, say we want to write a
> function which takes two integers and returns  the product and quotient
> of them.
>
> muldiv(First, Second) ->
>     case is_integer(First) of
>         true ->
>             case is_integer(Second) of
>                 true ->
>                     Product = First * Second,
>                     case Second =/= 0 of
>                         true ->
>                             Quotient = First div Second,
>                             {ok, {Product, Quotient}};
>                         false ->
>                             {error, "Second must not be zero!"}
>                     end;
>                 false ->
>                     {error, "Second must be an integer!"}
>             end;
>         false ->
>             {error, "First must be an integer!"}
>     end.
>
>
> Ugly, at least I think this "rocket" is not beautiful. Even worse, if
> requirement changed, you should modify this code on a large scale. To avoid
> this problem, you can just rewrite your code like this
>
> muldiv(First, Second) ->
>     do@([esugar_do_transform_error ||
>         case is_integer(First) of
>         true -> return(next);
>         false -> fail("First must be an integer!")
>         end,
>         case is_integer(Second) of
>         true -> return(next);
>         false -> fail("Second must be an integer!")
>         end,
>         Product = First * Second,
>         case Second =/= 0 of
>         true -> return(next);
>         false -> fail("Second must not be zero!")
>         end,
>         Quotient = First div Second,
>         return({Product, Quotient})
>     ]).
>
>
> This idea came from the Haskell's do grammer, and to use this grammer, you
> just need to write a error monad.
>
> This parse transform code is one module of my esugar(An Erlang Syntactic
> Sugar Library) library, and the address is (https://github.com/dploop/
> esugar)
>
> I'm glad to discuss with you about how to use it or improve it(because I
> just write this toy for fun at the begining).
>
>
> ------------------------------
> dploop@REDACTED
>
>
> *From:* code wiget <codewiget95@REDACTED>
> *Date:* 2017-09-25 21:25
> *To:* Erlang-Questions Questions <erlang-questions@REDACTED>
> *Subject:* [erlang-questions] Nested Case Statements v.s. multiple
> functions
> 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
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20170926/bbbaa02b/attachment.htm>


More information about the erlang-questions mailing list