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

Fred Hebert mononcqc@REDACTED
Wed Oct 3 04:27:02 CEST 2018


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.

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.

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.

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.

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

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.



More information about the eeps mailing list