<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><h3><span class="gmail-m_-8746844382255813045gmail-m_7746986015464219343gmail-mw-headline">EEP-0049 Value-based Error handling mechanisms</span></h3>
<a name="m_-8746844382255813045_m_7746986015464219343_The_problem_to_solve" id="gmail-m_-8746844382255813045gmail-m_7746986015464219343gmail-The_problem_to_solve"></a><h4><span class="gmail-m_-8746844382255813045gmail-m_7746986015464219343editsection"></span><span class="gmail-m_-8746844382255813045gmail-m_7746986015464219343gmail-mw-headline">The problem to solve </span></h4>
<p>Our interpretation of the EEP is that the author tries to solve 2 somewhat separate problems with
one single solution.
</p>
<ul><li> Replace or simplify deeply-nested case ... end expressions, and
 prevent using exceptions for control flow (with language support in 
this case).
</li><li> Encouraging standards <span style="font-family:monospace,monospace">{ok,Result}|{error,Reason}
</span></li></ul>
<p>We agree about that it would be nice to be able to replace or 
simplify deeply-nested case ... end expressions except  that we don't 
see a problem with using throw (a mechanism to make a non local return) 
as long as it 
is done in a safe way. We don't regard throw as an exception, and it is 
documented as "a non local return".
</p><p>We also agree that it would be good to encourage a standard 
pattern for function returns. But we are not there now and we would like
 to see something more flexible than hard coded support in the language.
</p>
<a name="m_-8746844382255813045_m_7746986015464219343_Comments_on_the_solution" id="gmail-m_-8746844382255813045gmail-m_7746986015464219343gmail-Comments_on_the_solution"></a><h4><span class="gmail-m_-8746844382255813045gmail-m_7746986015464219343editsection"></span><span class="gmail-m_-8746844382255813045gmail-m_7746986015464219343gmail-mw-headline">Comments on the solution </span></h4>
<p>In most of the examples where we find usage of nested case, the 
unwanted result (<span style="font-family:monospace,monospace">{error, Reason}</span> in this case) is not just returned, 
there is some other actions performed as well before returning. In those
 cases the proposed solution does not help.
</p>
<ul><li> We don't like a language construct which is hard coded to support ok,<span style="font-family:monospace,monospace">{ok,Result}, {error,Reason}</span>.
</li><li> the use of underscore <span style="font-family:monospace,monospace">_ <~</span> to mean a match with <span style="font-family:monospace,monospace">ok</span> is not a hit, it will make programs harder to read
</li><li> We are against the introduction of <i>unwrapexprs</i> that cannot be used everywhere where expressions are allowed. 
</li><li> The <i>unwrapexpr</i> changes the scoping rules and can not be used in nested expressions and not outside begin ... end.
</li></ul>
<p>It is perfectly possible to use throw and try catch to replace or 
simplify deeply-nested case ... end expressions in the same way as
the proposed language extension does.
</p>
<a name="m_-8746844382255813045_m_7746986015464219343_Example" id="gmail-m_-8746844382255813045gmail-m_7746986015464219343gmail-Example"></a><h5><span class="gmail-m_-8746844382255813045gmail-m_7746986015464219343editsection"></span><span class="gmail-m_-8746844382255813045gmail-m_7746986015464219343gmail-mw-headline">Example </span></h5>
<pre>commit_write2(OpaqueData) ->
    Ref = erlang:make_ref(),
    Ok = fun(ok) -> ok; ({ok,R}) -> R; ({error,_Reason} = E) -> throw( {Ref,E}) end,
    try
        Ok(disk_log:sync(OpaqueData#backup.file_desc)),
        Ok(disk_log:close(OpaqueData#backup.file_desc)),
        Ok(file:rename(OpaqueData#backup.tmp_file, OpaqueData#backup.file)),
        {ok, OpaqueData#backup.file}
    catch
        {Ref,E} ->
            E
    end.
</pre>
<pre>%% We could simplify for the user even more and at the same time encourage the
%% standard pattern ok, {ok,Result}, {error,Reason} by creating a library 
%% function like this (and perhaps place it in stdlib). To start with the user can
%% make his own function or fun for this.

ok() ->
    Ref = erlang:make_ref(),
    Ok = fun(ok) -> ok; 
            ({ok,R}) -> R; 
            ({error,_Reason} = E) -> 
                 throw( {Ref,E}) 
         end,
    {Ref,Ok}.

</pre>
<pre>%% Here is the same example using the library function
commit_write3(OpaqueData) ->
    {Ref,Ok} = ok(),
    try
        Ok(disk_log:sync(OpaqueData#backup.file_desc)),
        Ok(disk_log:close(OpaqueData#backup.file_desc)),
        Ok(file:rename(OpaqueData#backup.tmp_file, OpaqueData#backup.file)),
        {ok, OpaqueData#backup.file}
    catch
        {Ref,E} ->
            E
    end.
</pre>
<p><br>
</p>
<pre>%% This is another example from EEP 49
maybe() ->
    case file:get_cwd() of
        {ok, Dir} ->
            case
                file:read_file(
                  filename:join([Dir, "demo", "data.txt"]))
            of
                {ok, Bin} ->
                    {ok, {byte_size(Bin), Bin}};
                {error, Reason} ->
                    {error, Reason}
            end;
        {error, Reason} ->
            {error, Reason}
    end.
</pre>
<p><br>
</p>
<pre>%% The example above can be written like this without any new language 
%% constructs and the ok() function as a library function
%%
-spec maybe2() -> {ok, non_neg_integer()} | {error, term()}.
maybe2() ->
    {Ref,Ok} = ok(),
    try
        Dir = Ok(file:get_cwd()),
        Bin = Ok(file:read_file(filename:join([Dir, "demo", "data.txt"]))),
        {ok, {byte_size(Bin), Bin}}
    catch
        {Ref,ErrorReason} ->
            ErrorReason
    end.
</pre>
<a name="m_-8746844382255813045_m_7746986015464219343_Summary" id="gmail-m_-8746844382255813045gmail-m_7746986015464219343gmail-Summary"></a><h4><span class="gmail-m_-8746844382255813045gmail-m_7746986015464219343editsection"></span><span class="gmail-m_-8746844382255813045gmail-m_7746986015464219343gmail-mw-headline">Summary </span></h4>
<ul><li>We say no to the proposed language extensions. We don't think they are general enough and we also see some problems with them.
</li><li> The same effect can be achieved safely with the current language using throw, try...catch.
</li><li> Encouraging <code>ok, {ok,Result}, {error,Reason}</code> as 
results from functions can be done in other ways, for example through 
library functions. These values should not be special to the <em>language</em>.
</li><li>We also want to thank the author for a very well thought through and well documented proposal which has triggered us to think about possible 
solutions in this area. We really appreciate the effort.</li></ul><p>/Kenneth, Erlang/OTP Ericsson<br></p></div></div><div class="gmail-adL"><br> </div></div></div>