Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: Go 2: onErr simple macro for common case error handling. A #32437 counter-proposal. #32946

Closed
ohir opened this issue Jul 4, 2019 · 5 comments
Labels
error-handling Language & library change proposals that are about error handling. FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Milestone

Comments

@ohir
Copy link

ohir commented Jul 4, 2019

This is a counter-proposal to the #32437. It uses the on err words proposed in #32611and #32848 but unlike #32611 it is specifically restricted to the ubiquitous and a defacto standard err identifier (variable) followed by a block, control-flow statement; or a call to the built-in panic() function.

Usage examples

c, err := fn()
onErr continue

c, err := fn()
onErr {
    x++
    break
}

if r, err := fn(); onErr && triesleft > 0 {
  triesleft--
  continue retry
}

if c, err := fn(); onErr {
    return 0, err
}

Go Specification amendments

Operators

log_op = "||" | "&&" .

Statements addition:

ctlflstmt       = ( ReturnStmt | BreakStmt | ContinueStmt | GotoStmt )
OnErrStmt       = "onErr" ctlflstmt
OnErrSimpleStmt = "onErr" ( block | log_op )

Blocks addition:

6.  ctlflstmt statement in the OnErrStmt is considered to be in its own implicit block.

onErr macro

to be added after Defer_statements.

The onErr macro simplifies repeatable error handling, checking whether err variable is not nil. Ie. the very onErr always is expanded to mean if err != nil. The err identifier must be in the scope.

After an onErr either a block, or five possible statements are allowed: continue, break, return, goto, and a call to panic(…) built-in. Then expansion occurs:

  1. The onErr always is expanded to the if err != nil statement.
  2. If there is a block or a logical or or and operator after the onErr, expansion ends.
  3. If there is an allowed statement, it acts as given in an implicit curly braces.

Implementation:

after recognizing an onErr token, hardcode the if err != nil template and subparse rest of the line. The core of the expansion likely will land somewhere within parser.go:2040 scope in the case _Onerr:

A macro?

@griesemer suggested that try is just a macro. So I dare to propose a macro too, based on an 'invisible semicolons' precedence and with a straightforward implementation.

thats all,

enjoy!

ohir


Edits:

  • added explicit log_op to allow expansion in expression chains. Add usage example for it.
@gopherbot gopherbot added this to the Proposal milestone Jul 4, 2019
@ianlancetaylor ianlancetaylor added v2 A language change or incompatible library change LanguageChange labels Jul 5, 2019
@beoran
Copy link

beoran commented Jul 5, 2019

I think that in stead of implementing a specific built in "macro" such as try(), or tryErr, Go need a hygienic macro feature where we can define macros ourselves. Then everyone can choose how to do error handling as they like. #32620

@munnerz
Copy link

munnerz commented Jul 5, 2019

As you've noted, this is short-hand for if err != nil in all cases. Personally I do not think this is a particularly useful construct nor does it add any more value beyond saving a handful of characters (as well as allowing syntax such as onErr continue, which is effectively a text substitution that also expands to include braces).

I feel like this adds extra cognitive overload, without really delivering value to developers (my 2c!).

Go need a hygienic macro feature where we can define macros ourselves

I'm a big -1 on this idea - it will lead to everyones codebase being 'specialised', with custom macros and definitions all over the place. Switching between projects because a huge mental burden, and it starts to smell of similar features in other, older languages that quickly grow out of control.

@ohir
Copy link
Author

ohir commented Jul 6, 2019

I feel like this adds extra cognitive overload, without really delivering value to developers (my 2c!).

Note that I am in the 'leave if err!= nil alone' camp and this counter proposal was published to show simpler solution to a common whine :)

@ianlancetaylor
Copy link
Contributor

The proposal says that onErr is always expanded to if err != nil, but in that case how does this example work?

if r, err := fn(); onErr && triesleft > 0 {
  triesleft--
  continue retry
}

@ianlancetaylor
Copy link
Contributor

Simply replacing if err != nil or err != nil with onErr is not enough of a benefit for a language change.

The fact that this adds special language treatment to the identifier err is also unfortunate.

-- writing for @golang/proposal-review

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
error-handling Language & library change proposals that are about error handling. FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

6 participants