<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>