IMO, `returnif <bool>, <expr...>` reads awkwardly. If anything, it should
really be `return <expr...> if <bool>`. At which point it also becomes
clear that this isn't actually much of an improvement over `if <bool> {
return <expr...> }`.

On Tue, Nov 10, 2020 at 11:59 PM Tyler Compton <xavi...@gmail.com> wrote:

> The "try proposal" and some others identified and solved two problems:
>
> a. The verbosity of using a full if statement to check error values
> b. The verbosity of applying wrapping and other error handling logic to
> every place where an error is returned
>
> This proposal only addresses Problem A. Maybe that's okay, because it
> seems like addressing Problem B often leads to complicated control flow
> issues.
>

The way I think about it at least, is that the try proposal was rejected
*because* it solved problem A specifically (and the returnif mentioned here
doesn't; `returnif` stays a statement).

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
>>
>> On Mon, Nov 9, 2020, 2:57 PM Ian Lance Taylor <i...@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+unsubscr...@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+unsubscr...@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/CAEkBMfEcqx0QT_eCDTqT%3DvE8%2Bkuxi7A6WPY0A7McaoHHnJ5o2Q%40mail.gmail.com.

Reply via email to