On Wed, Nov 11, 2020 at 5:02 PM Jeremy French <ibi...@gmail.com> wrote:

> *shrug* As you said, returnif is still a statement, and yet it reduces the
> minimum boilerplate from 3 lines down to 1.
>

There's a way to get that without a language change - you can have gofmt
make `if err != nil { return … }` into a 1-liner. It's virtually identical,
apart from some extra braces and a re-shuffling of some letters. And it has
been proposed in the past. It didn't get anything close to broad support.

It sort of seems like maybe one of your goals is to find a solution that
> everyone will agree with.
>

Far from it. In my opinion, `try` was by a wide margin the best solution to
the problem proposed so far. So if we'd do anything, I'd hope it would be
that. Even though many, many people disagree with it (obviously - that's
why it was rejected).

But I'm not trying to be normative here. I'm trying to be predictive. I've
been reading and participating in this discussion for years and I've seen
dozens and dozens of these designs and read the argument on both sides. I'm
not trying to say your idea *should* be rejected, I'm saying that I feel
certain that it *will* be rejected. Not because "not everyone will agree
with it", but because not enough and/or not the right people will.

  And if so, then I agree with you that that becomes an impossible task
> once a community reaches a certain size.  I'm really just trying to find an
> objectively better solution to what we have now, and I think the reason
> returnif works better than the other proposals, is only because it
> recognizes the problem more correctly.  It's not really an error handling
> issue.  It's a flow control one.
>
> --
>
>
>>
>>> 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...@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/d4bb6c34-2ed2-4ff1-93df-d27cc6b42919n%40googlegroups.com
> <https://groups.google.com/d/msgid/golang-nuts/d4bb6c34-2ed2-4ff1-93df-d27cc6b42919n%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/CAEkBMfFOVFJWiOrygV75pz6uVP2Y43g6pjG3sm8J_u4TC4-Zmg%40mail.gmail.com.

Reply via email to