Skip to content

Instantly share code, notes, and snippets.

@ferd

ferd/eep-49.erl Secret

Created October 23, 2020 14:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ferd/2f1134fd88615354fbf89c068216b259 to your computer and use it in GitHub Desktop.
Save ferd/2f1134fd88615354fbf89c068216b259 to your computer and use it in GitHub Desktop.
begin
{ok, A} <- f(),
B = g(A),
{ok, C=[_|_]} <- h(A,B),
{ok, {A,B,C}}
else
{error, _Unexpected} -> error;
{ok, _Unexpected} -> error
end
%% Translating to using only case expressions
case begin
case f() of
{ok, A} ->
B = g(A),
case h(A,B) of
{ok, C=[_|_]} ->
{value, {ok, {A,B,C}}};
Other ->
{'else', Other};
end;
Other ->
{'else', Other}
end
end of
%% good clause
{value, X} -> X;
%% else clause
{'else', X} ->
case X of
{error, _Unexpected} -> error;
{ok, _Unexpected} -> error
end
end
begin
{ok, A} <- f(), %% A
B = g(A), %% B
{ok, C=[_|_]} <- h(A,B), %% C
ok <- begin %% D <- E
D = {A,B,C}, %% F
{error, _} <- i(D) %% G
end,
ok <- begin %% H <- I
{error, expected} <- i(D) % D still in scope! %% J
else
ok -> ok %% K
end,
{ok, {A,B,C}} %% L
else
{error, _Unexpected} -> error; %% M
{ok, _Unexpected} -> error %% N
end
%% translating using only case expressions
case begin
case f() of %% A
{ok, A} ->
B = g(A), %% B
case h(A,B) of
{ok, C=[_|_]} -> %% C
case %% D
case begin %% E
D = {A,B,C}, %% F
case i(D) of %% G
{error, _}=V ->
{value, V};
Other ->
{'else', Other}
end
end of %% E (still)
%% no else clause, return both flows
{value, V} -> V;
{'else', V} -> V
end
of %% D (still)
ok ->
case %% H
case begin %% I
case i(D) of %% J
{error, expected} = V -> {value, V};
Other -> {'else', Other}
end
end of
{value, V} -> V;
{'else', ok} -> ok %% K
end
of
ok ->
{value, {ok,{A,B,C}}}; %% L
Other ->
{'else', Other}
end;
Other ->
{'else', Other};
Other ->
{'else', Other};
end;
Other ->
{'else', Other}
end
end of
%% good clause
{value, X} -> X; % L
%% else clause
{'else', X} ->
case X of
{error, _Unexpected} -> error; % M
{ok, _Unexpected} -> error % N
end
end
@ferd
Copy link
Author

ferd commented Oct 29, 2020

Minor variant where 'case clause' errors are replaced by 'else clause' errors:

begin
    {ok, A} <- f(),
    B = g(A),
    {ok, C=[_|_]} <- h(A,B),
    {ok, {A,B,C}}
else
    {error, _Unexpected} -> error;
    {ok, _Unexpected} -> error
end

%% Translating to using only case expressions

case begin
    case f() of
        {ok, A} ->
            B = g(A),
            case h(A,B) of
                {ok, C=[_|_]} ->
                    {value, {ok, {A,B,C}}};
                Other ->
                    {'else', Other};
            end;
        Other ->
            {'else', Other}
    end
end of
    %% good clause
    {value, X} -> X;
    %% else clause
    {'else', X} ->
        case X of
            {error, _Unexpected} -> error;
            {ok, _Unexpected} -> error
        end;
    ElseErr ->
        erlang:error({else_clause, ElseErr})
end

begin
    {ok, A} <- f(),                                         %% A
    B = g(A),                                               %% B
    {ok, C=[_|_]} <- h(A,B),                                %% C
    ok <- begin                                             %% D <- E
        D = {A,B,C},                                        %% F
        {error, _} <- i(D)                                  %% G
    end,
    ok <- begin                                             %% H <- I
        {error, expected} <- i(D) % D still in scope!       %% J
    else
        ok -> ok                                            %% K
    end,
    {ok, {A,B,C}}                                           %% L
else
    {error, _Unexpected} -> error;                          %% M
    {ok, _Unexpected} -> error                              %% N
end

%% translating using only case expressions

case begin
    case f() of                                             %% A
        {ok, A} ->
            B = g(A),                                       %% B
            case h(A,B) of
                {ok, C=[_|_]} ->                            %% C
                    case                                    %% D
                        case begin                          %% E
                            D = {A,B,C},                    %% F
                            case i(D) of                    %% G
                                {error, _}=V ->
                                    {value, V};
                                Other ->
                                    {'else', Other}
                            end
                        end of                              %% E (still)
                            %% no else clause, return both flows, no errors possible
                            {value, V} -> V;
                            {'else', V} -> V
                        end
                    of                                      %% D (still)
                        ok ->
                            case                            %% H
                                case begin                  %% I
                                    case i(D) of            %% J
                                        {error, expected} = V -> {value, V};
                                        Other -> {'else', Other}
                                    end
                                end of
                                    {value, V} -> V;
                                    {'else', ok} -> ok;      %% K
                                    ElseErr -> erlang:error({else_clause, ElseErr})
                                end
                            of
                                ok ->
                                    {value, {ok,{A,B,C}}};  %% L
                                Other ->
                                    {'else', Other}
                            end;
                        Other ->
                            {'else', Other};
                Other ->
                    {'else', Other};
            end;
        Other ->
            {'else', Other}
    end
end of
    %% good clause
    {value, X} -> X; % L
    %% else clause
    {'else', X} ->
        case X of
            {error, _Unexpected} -> error; % M
            {ok, _Unexpected} -> error;     % N
            ElseErr -> erlang:error({else_clause, ElseErr})
        end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment