On Wed, Nov 11, 2020 at 2:43 AM Jeremy French <ibi...@gmail.com> wrote:

> I certainly can't speak for the whole community, but for me, the key word
> here is verbosity.  I don't care (too much) whether it's technically a
> statement or an expression or a macro. What I care about is signal to noise
> ratio in my code.  What I really want in my fantasies is for my code to be
> 100% happy path.
>

The majority (or maybe the loud minority - either way, definitely Go's
design philosophy) of the community disagrees with you here.
Error handling should be explicit, that seems to be a hard requirement.


> I'm wondering if people object more to that or to the fact that the
> surrounding "if" qualifies as a statement rather than an expression.
>

What I'm saying is that one causes the other. You mention the 25% ratio.
That ratio is based on line-count and the only reason why the
error-handling takes up more lines, is because it uses a statement. So my
point is, to meaningfully reduce the "verbosity", you have to get away from
that.

Incidentally, this is also why I think this version of returnif is
> critically different from the version that reads "returnif <err>" because
> it doesn't require the compiler/runtime to know what an error is or when it
> should qualify as something that needs to be returned.
>

I agree. I disagree that it's critically different from what we have today.


> In the two-expression version, the developer is in complete control.
>
> --
>
>
>>
>> The main criticism of try, as far as I remember, was that in something
>> like
>> `F(try G(), try H())` it wasn't clear enough how the control flow worked.
>> But that's a direct consequence of creating an error handling *expression*
>> (as opposed to a statement).
>>
>> Realizing that was the point where I kind of gave up on the idea of ever
>> "solving" the error handling problem. To me, error handling requiring a
>> statement is the main gripe of most people - it's why it seems verbose and
>> repetitive to people. But if that's so, but the community rejects any
>> proposal that makes it an expression, then the problem becomes unsolvable.
>>
>>
>>> I do like that this proposal doesn't treat errors in a special way. I
>>> could imagine it could be useful when checking if a key is in a map, for
>>> example.
>>>
>>> value, ok := myMap["value"]
>>> returnif !ok, errors.New("Oh no! Missing key 'value'!")
>>>
>>> Another thought: Should returnif allow a statement before the boolean
>>> expression like if does?
>>>
>>> returnif value, ok := myMap["value"]; !ok, errors.New("Oh no!")
>>>
>>> That could make code more compact but looks very busy to me. My first
>>> impression is that this shouldn't be allowed.
>>>
>>> I think I would be okay with reading and writing code like this. The
>>> level of complexity here is certainly lower than other proposals, although
>>> the value is arguably lower as well since it doesn't solve as many
>>> problems. I'll defer to others here.
>>>
>>>
>>> On Mon, Nov 9, 2020 at 1:52 PM Jeremy French <ibi...@gmail.com> wrote:
>>>
>>>> Hm, yep. Very similar. Interestingly, the only cohesive objections I
>>>> can see in those threads are to the minor details that are different from
>>>> what I'm saying. Still, though - at least the idea has been presented
>>>> before.
>>>>
>>>> Jeremy French
>>>> 607-444-1725 <(607)%20444-1725>
>>>>
>>>> On Mon, Nov 9, 2020, 2:57 PM Ian Lance Taylor <ia...@golang.org> wrote:
>>>>
>>>>> On Mon, Nov 9, 2020 at 11:20 AM Jeremy French <ibi...@gmail.com>
>>>>> wrote:
>>>>> >
>>>>> > First, the caveat.  I know error handling is a long-standing
>>>>> discussion.  I know there has been lots of debate on error handling, and 
>>>>> it
>>>>> can seem like there are no more new ideas to be had on the topic.  And I
>>>>> have looked at several/most of the most popular proposals, and there are
>>>>> quite a few that bear similarity but are critically different in important
>>>>> aspects to this proposal. If this has been proposed before with the same
>>>>> effective fingerprint, I haven't been able to find it after several hours
>>>>> of due diligence.  I'm interested in hearing any and all (well-reasoned)
>>>>> thoughts on the matter, but if there's a flaw in my logic, I don't see it
>>>>> yet.
>>>>> >
>>>>> > In short, the proposal is to create a conditional return statement,
>>>>> e.g. "returnif" of the form:
>>>>> >    returnif [bool], [returnvalue],...
>>>>> >
>>>>> > This is syntactic sugar for:
>>>>> > if [bool] {
>>>>> >     return [returnvalue],...
>>>>> > }
>>>>> >
>>>>> > of which, the immediate benefit is:
>>>>> > returnif err!=nil, err
>>>>> >
>>>>> > or alternatively:
>>>>> >
>>>>> > returnif myErrorChecker(err), myErrorWrapper(err, "Some text.")
>>>>> >
>>>>> > Here's my reasoning.  Go Error Handling in is current form is
>>>>> extremely correct, precise, explicit, and clear.  All very good things.
>>>>> Really the only problem with it is the repetitious verbosity.  A
>>>>> programmer's instinctive reaction to repetitious verbosity is to wrap it 
>>>>> in
>>>>> a function.  The infamous "if err != nil {return err}", although
>>>>> repetitious and ubiquitous, cannot effectively be encapsulated to "return
>>>>> someErrorChecker()", because the return statement is unconditional.  Once 
>>>>> I
>>>>> start a statement with return, nothing I can do later in the statement or
>>>>> within a called function can change whether or how that return alters flow
>>>>> control.  This, I think, is the quintessential problem with the current
>>>>> error handling methodology.  This proposal addresses that without
>>>>> sacrificing any of the good things about error handling in Go.  Error
>>>>> handling is still explicit.  Errors can still be treated as values. Proper
>>>>> error handling and annotating is blessed but optional. The behavior of
>>>>> defer is unaffected.  It is still simple to understand, and easy to read.
>>>>> And it's entirely backwards compatible.
>>>>> >
>>>>> > Also, while the most obvious benefit is in error handling, this is
>>>>> not technically just an error handling solution. It is completely
>>>>> unopinionated on the type of values it returns, or whether they qualify as
>>>>> an error or not.  I can foresee enterprising gophers finding other uses 
>>>>> for
>>>>> this keyword, and quite possibly even new useful design patterns could
>>>>> emerge as a result.
>>>>> >
>>>>> > Possible Objections:
>>>>> >
>>>>> > It could be seen to violate the "one way to do things" principle.
>>>>> However,
>>>>> >
>>>>> > It violates this rule much less than almost all of the other
>>>>> proposals for error handling.
>>>>> > If, under the covers, it's just code substitution, then there's
>>>>> still only one actual avenue of execution in the compiled objects.
>>>>> > There is precedent for this type of shortcut when the benefits are
>>>>> so widespread and the sugar improves readability. For example,
>>>>> > } else if isTrue {
>>>>> >     doSomething()
>>>>> > }
>>>>> > is sugar for
>>>>> > } else {
>>>>> >     if isTrue {
>>>>> >         doSomething()
>>>>> >     }
>>>>> > }
>>>>> >
>>>>> > "It's just a variation on other existing proposals."
>>>>> >
>>>>> > This proposal avoids or addresses all the objections listed in the
>>>>> error handling meta issue #40432, and as such, may be a variation, but
>>>>> varies sufficiently to create a different result set.
>>>>> > From the meta issue:
>>>>> >
>>>>> > The check/handle proposal.
>>>>> >
>>>>> > One major reason this was rejected was a lack of clarity between
>>>>> handle and defer.
>>>>> >
>>>>> > The try proposal.
>>>>> >
>>>>> > One major reason this was rejected was the additional flow control:
>>>>> a complex expression using try could cause the function to return. Go
>>>>> currently has no flow control constructs at the expression level, other
>>>>> than panic which does more than just return from a function.
>>>>> >
>>>>> > Special characters, often ! or ?, that insert an error check in a
>>>>> function call or assignment.
>>>>> >
>>>>> > These are typically rejected because they are cryptic. Often a
>>>>> single ! or other character leads to a change in flow control.
>>>>> >
>>>>> > Simplifications of if err != nil, to reduce boilerplate.
>>>>> >
>>>>> > These are typically rejected either because they don't reduce the
>>>>> boilerplate enough to make it worth changing the language, or because they
>>>>> are cryptic.
>>>>> >
>>>>> > What about edge cases?  How to handle else clauses or additional
>>>>> conditional logic based on error type etc.?
>>>>> >
>>>>> > It's my belief that else clauses too rare to justify additional
>>>>> syntax.  If you need an else/else if clause, you can use the existing
>>>>> syntax and lay out your conditionals on more lines. Also - you know - any
>>>>> code after a return statement is essential an else clause anyway.
>>>>> > By making [bool] an expression, any additional logic may be handled
>>>>> by the programmer in a determinant function that returns a boolean.  This
>>>>> puts this type of flow control in the hands of the developer.
>>>>> > The short statement currently available with if and for statements
>>>>> (if err:=doSomething(); err != nil) could be implemented in a similar
>>>>> fashion, but my personal vote would be to disallow it, as most of the
>>>>> simplicity and clarity of this proposal could be lost down that rabbit 
>>>>> hole.
>>>>> >
>>>>> > I believe the most critical difference between this proposal and
>>>>> previous ones is that this proposal addresses the core issue more
>>>>> directly.  The central problem to the current error handling methodology 
>>>>> is
>>>>> not actually specific to error handling.  That's just where it's most
>>>>> visible.  The core problem is essentially the fact that a child function
>>>>> cannot affect the conditional return of a parent function (barring further
>>>>> conditional logic), even with explicit permission by the parent function.
>>>>> This is not true with any other form of flow control.  This is why the
>>>>> current methodology feels wrong to developers, because they are disallowed
>>>>> from encapsulating repetitious logic in a way that is consistent with 
>>>>> other
>>>>> flow control statements.
>>>>> >
>>>>> > Anyway, that's my argument.  If anyone knows of a previous proposal
>>>>> that this duplicates, and/or knows why that one didn't/couldn't work, I'd
>>>>> be grateful for the explanation.
>>>>>
>>>>> For the record, similar but not quite identical:
>>>>>
>>>>> https://github.com/golang/go/issues/21161#issuecomment-366766924
>>>>> https://github.com/golang/go/issues/32811#issuecomment-508776641
>>>>>
>>>>> Ian
>>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "golang-nuts" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to golang-nuts...@googlegroups.com.
>>>> To view this discussion on the web visit
>>>> https://groups.google.com/d/msgid/golang-nuts/CA%2Bj6mhDjFAjpQTcpA3oJfwFKUYdhNn-1jB39FiYoe6nspUTg2g%40mail.gmail.com
>>>> <https://groups.google.com/d/msgid/golang-nuts/CA%2Bj6mhDjFAjpQTcpA3oJfwFKUYdhNn-1jB39FiYoe6nspUTg2g%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "golang-nuts" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to golang-nuts...@googlegroups.com.
>>>
>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/golang-nuts/CAA%3DXfu1RXATObiH-Lx_ZUQXqtT6DyJdR%3Dk9dbg-1KaMNoDL_wA%40mail.gmail.com
>>> <https://groups.google.com/d/msgid/golang-nuts/CAA%3DXfu1RXATObiH-Lx_ZUQXqtT6DyJdR%3Dk9dbg-1KaMNoDL_wA%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/fd01a242-c89d-4ab9-8266-c0f61cf177f6n%40googlegroups.com
> <https://groups.google.com/d/msgid/golang-nuts/fd01a242-c89d-4ab9-8266-c0f61cf177f6n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfEj8oKaVT9GgTdxwGc8JKy2kH5_mysGqf%2B7kFYkG0d5%2Bg%40mail.gmail.com.

Reply via email to