[eeps] EEP ???: Value-Based Error Handling Mechanisms

Raimo Niskanen raimo+eeps@REDACTED
Wed Oct 3 09:09:56 CEST 2018


On Tue, Oct 02, 2018 at 10:27:02PM -0400, Fred Hebert wrote:
> On 10/02, Raimo Niskanen wrote:
> >I somehow feel a need to be able to distinguish between ok and {ok,_}.
> >
> >In your example for Reducing Nesting, Mnesia, the
> >
> >  _ <~ disk_log:sync(...)
> >
> >is not exactly equivalent to
> >
> >  case disk_log:sync(...) of
> >      ok -> this;
> >      {error,Reason} -> that
> >  end
> >
> >since if disk_log:sync/1 would return {ok,_} that would be allowed after
> >the rewrite to use <~ but case clause before.
> >
> 
> That is correct. In the case of `_ <~ Exp` the more equivalent match 
> expression would be:
> 
>    case disk_log:sync(...) of
>        ok -> this;
>        {ok, _} -> this;
>        {error,Reason} -> that
>    end
> 
> >I think being able to narrow possibilities in the code is a good thing, but
> >I have not found a good way to squeeze it into this language extension.
> >But I would like to be able to somehow specify to allow ok but not {ok,_}
> >as a success value...
> 
> Essentially, a flat `ok` is made similar to `{ok, <null>}` by the 
> pattern: it is really trying to say "unpack the good value", whatever it 
> is.
> 
> You can allow `{ok, _}` but not `ok` by matching on `_Ignored <~ Exp` 
> since that binds a variable and 'ok' can't make that possible, but there 
> is indeed no way to say "I need this to be `ok` with no actual value 
> bound and also make sure nothing is returned aside from ok". This one 
> specific case would require you to use a case expression as you 
> currently would today.
> 
> To make a distinction between these, I think would involve one of the 
> following:
> 
> - ask for an explicit pattern (`{ok, _} <~ Exp` vs. `_ <~ Exp`, which 
>   means you can create invalid syntactic cases by using `{error, _} <~ 
>   Exp`)
> - allow the `<-` operator for exact matches (contains the caveats 
>   explained in earlier posts)
> - introduce some prefix operator
> - introduce a new kind of pattern to mean "No value returned", which is 
>   basically a terrible idea for a functional language IMO.
> 
> I don't think any of these are nice enough either, at least compared to 
> the convenience of being able to handle `ok` as a positive return value 
> in general. Might as well use a case expression for these.

Agreed.  Handling 'ok' as a positive return value is essential.

> 
> The problem goes away entirely if `ok` is not possible to use with the 
> construct (you have to extract a value), but my guess is that this would 
> instead encourage people in the community to use `{ok, undefined}` as 
> return values to fit with nicer workflows.

Agreed.

> 
> A quick search yields 17 functions in all of OTP that currently use this 
> possible return value in a signature:
> 
> $ ack -r '[^{]ok.*\|.*{ok,' | grep '\.erl' | wc -l
> 17
> 
> 2 of them are in test suites, at least 5 of them are using signatures 
> with over 3 variants of `ok | {ok, _} | {ok, _, _} | {ok, _, _, _}` 
> which wouldn't work anyway, and one of them is a false positive on the 
> regex.
> 
> Of the 11 left, the most notable one is possibly ssl:close/2 (and ~3-4 
> variants) where the function can be used both to close the socket and to 
> downgrade it to a non-ssl connection. I would argue that the proper 
> thing would have been to have a 'downgrade' function, but this isn't 
> what's at stake here.

Right.

> 
> In any case, the pattern is likely rare in terms of possible producing 
> sites, but I couldn't say how it goes as far as call-sites are 
> concerned.

The use I have in mind for matching 'ok' explicitly is simply that when you
write your code you know that the return value should be 'ok', and you want
to guard yourself from future mistakes where you e.g change the called
function to a not as equivalent as you thought.

Also for the code reader it is nice to know that there is no value
discarded here, and for the final value that you do not have to look up
the called function to know that the function you just wrote will only
return 'ok'.

So I am just for basic narrowing of possibilities...

I guess an empty pattern is not possible?

    begin
	Whom <~ id({ok,"world"}),
	<~ io:format("Hello, ~p!\n", [Whom])
    end

> 
> >
> >An interesting EEP.  A bit over-magical as Adam Lindberg thought - the
> >relation to {ok,_} and {error,_} feels rather hidden in the <~ operator.
> >But I do not have a better suggestion. :-/
> >
> 
> Alright. Is this basically the EEP being turned down, or more of a 
> general remark, though?

Nono, that, and all the above, are just my personal opinions.  Not the OTP
opinion.  And that remark was a general one along Adam Lindberg's line
that I also like the explicitness in Erlang, and this EEP hides the {ok,_}
and {error,_} patterns, which sacrifices explicitness for convenience.

I think the convenience of the programming pattern that becomes possible
is really useful, though.

> 
> I'm curious what the next steps are. If the overall feeling is "nice but 
> not nice enough", I'd rather see the EEP rejected than left to linger 
> for many years, as seems to be the case with multiple EEPs in the past, 
> so at least I know where to stand.

I accidentally jumped out of line when answering here...

A few internal meetings are coming up before there can be any OTP opinions.

-- 

/ Raimo Niskanen



More information about the eeps mailing list