Closed DrGo closed 1 year ago
I'm not arguing for or against this proposal, but it could simply use 'else' instead of introducing a new keyword. It should be unambiguous to parse in that position.
Besides the slightly different syntax, what makes this sufficiently distinct from previous proposals like #41908 #56895
Besides the slightly different syntax, what makes this sufficiently distinct from previous proposals like #41908 #56895
Thanks. I did not see the latter proposal despite searching the wiki entry on error handling..However, in my proposal I am focused on addressing the cultural issues that blocked progress on solving this problem. Also orelse
is meant to be different from `else' to avoid giving the impression that it can be used anywhere where a returned value is not nil. This is specifically an error-handling mechanism.
Also looks similar to #32848 and #32946.
The solution space is very restricted... so it is not surprising that there will be similarities to previous proposals. The important thing here in my view is that we are having a discussion about an issue that is important to many Go users. Although I suspect that a vocal minority has already decided that the more verbose error handling the better, and that Go will die a slow painful death if another option was to be introduced!
Although I suspect that a vocal minority has already decided that the more verbose error handling the better
It could also be that those who are unsatisfied with the current error handling are a vocal minority.
I agree that it is worth discussing. The place to discuss it is golang-nuts, and there is already an active discussion there. GitHub issues turn out to be bad at handling generalized discussions, because they are not threaded and when there are lots of comments they start hiding some. So if you want to discuss error handling, please do, but not here. Keep the issue tracker for specific proposals. Thanks.
No.. we have evidence from several surveys that it is a significant number of people. The important thing here is that the changes proposed do not affect those who prefer to use the current approach.. it does not complicate the language (in fact it simplifies error handling and learning and teaching it) and it does not affect compiling or runtime performance so it is hard to see why the resistance.
I agree that it is worth discussing. The place to discuss it is golang-nuts, and there is already an active discussion there. GitHub issues turn out to be bad at handling generalized discussions, because they are not threaded and when there are lots of comments they start hiding some. So if you want to discuss error handling, please do, but not here. Keep the issue tracker for specific proposals. Thanks.
I started that discussion on this particular proposal and overall the debate was encouraging so I proceeded to put a formal proposal.. I do not mean for this to be just a discussion. I think this is an appropriate time to resurface such a proposal after all the more urgent issues, e.g., modules and generics, were addressed. To me the obstacle to addressing this issue has been mostly cultural. I am hoping that the many recent changes in Go may have blunted the sharp divide between the error-handling camps so that we can find a compromise solution that works for all. Thanks
No.. we have evidence from several surveys that it is a significant number of people.
The surveys indicate a significant number, but do not confirm whether it constitutes a majority. What we know is that no single error handling proposal has garnered a majority of support so far.
it does not complicate the language (in fact it simplifies error handling and learning and teaching it)
Introducing more ways of doing the same adds complexity to a language.
I think what happens with this issue is that the many people who want change are not as motivated as the "error handling must be painful camp".
Introducing more ways of doing the same adds complexity to a language.
That is a generalization.. often true. but not in this case. Complexity is not just about the count of keywords or ways of doing things.. it is anything that unnecessarily add to the mental load of the reader. I provided above some concrete way of measuring it in this particular case: the ratio of the number error handling lines to program logic lines.
in fact it simplifies error handling and learning and teaching it
You can say a lot about the current way of error handling (boring, repetitive, etc.), but not that it's difficult to learn or teach. In fact it's so simplistic that even the noobiest of programming noobs understands it immediately.
this proposal does not change that, it will stay as boring as ever... it just creates a concise way that makes it easier to teach it e.g., by including it in code samples in tutorials instead of assigning the error to _ and asking the readers to manage the errors properly which is often the case even in the good Go books.
Please let's not have a discussion about error handling in general on this issue. Please only discuss this specific proposal. Thanks.
The solution space is very restricted... so it is not surprising that there will be similarities to previous proposals.
OK, but those previous proposals were rejected. We don't want to repeatedly revisit past decisions. If we are to consider a proposal that is similar to previously rejected proposals, we want to see new information that explains why this proposal is different.
Does orelse allow any statement? Or just returns?
Note that the condition for the orelse statement is implicit here (err!= nil)
I'm not too sure about that.
( the advantage of the current error handling is that it uses the most basic of all control-flow structure, not sure that's something that can be replaced easily)
Thanks Ian, I agree with not having general discussions here and will refrain from that.
I outlined several benefits of this proposal that I do not believe were discussed in the previous proposals including scoping of variables and integration with recently introduced facilities in the language. But as I mentioned I do believe the environment is different. This issue as I am sure you know has never been about the technical details; more about strongly held views about change which I hope have shifted a bit given all the recent developments.
A new keyword is not impossible, but it is a big lift for any language change. That is because introducing a new keyword will break any existing programs that use that keyword as a variable name, as in orelse := 0
. That doesn't mean that we can't do it. All language changes are a cost/benefit decision. A new keyword is a heavy cost, and it requires a correspondingly big benefit.
This proposal changes
r, err := os.Open(src)
if err != nil {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
into
r, err := os.Open(src) orelse return fmt.Errorf("copy %s %s: %v", src, dst, err)
Ignoring the text that is the same, this changes \nif err != nil {\n\n}
to orelse
. That is, it changes four lines, six tokens, and 19 characters to one line, one token, and 6 characters.
Part of the boilerplate of error handling is , err
on the left of the :=
. This proposal doesn't remove that bit of boilerplate, unlike the try
proposal (#32437).
The proposal introduces a syntax that is unlike any other syntax in Go, with an optional block. It moves error handling over to the right, which some like but others do not (see #57645, notably https://github.com/golang/go/issues/57645#issuecomment-1374645953).
It's not entirely clear to me what is permitted to follow orelse
other than return
and {
.
Does orelse allow any statement? Or just returns?
Good question. I think it should be only return or {...} block
Does orelse allow any statement? Or just returns?
Note that the condition for the orelse statement is implicit here (err!= nil)
I'm not too sure about that.
( the advantage of the current error handling is that it uses the most basic of all control-flow structure, not sure that's something that can be replaced easily)
I guess what I am saying is that the orelse
(instead eg of just else
) dedicated keyword makes the potential change in program flow due to error explicit.
Ignoring the text that is the same, this changes
\nif err != nil {\n\n}
toorelse
. That is, it changes four lines, six tokens, and 19 characters to one line, one token, and 6 characters.
I suggested a metric to measure the reduction in boilerplate (# err handling lines: # program logic lines) which I think is a fair way to measure the mental burden of reading and understanding error-heavy code like the CopyFile routine. I prefer it to counting tokens in a single error handling line because the latter does not account for mental obstacles like the need to scroll back and forth to see the entirety of a routine (which is especially true for a learner or a code reviewer).
Part of the boilerplate of error handling is
, err
on the left of the:=
. This proposal doesn't remove that bit of boilerplate, unlike thetry
proposal (#32437).
correct...I intentionally left that in because it makes it easier to read subsequent code (it is clear what the err var refers to in the orelse block)..
The proposal introduces a syntax that is unlike any other syntax in Go, with an optional block.
The block can be made mandatory like with other conditionals.
It's not entirely clear to me what is permitted to follow
orelse
other thanreturn
and{
.
was thinking just a {} or a return as a special case (but see above)
After read the proposal, I'd like to introduce a derivative idea for consideration. The aim is to provide a more concise way this, while remaining explicit and consistent with Go's established idioms.
f, err := os.Open("file.txt"); else { return err }
data, err := ioutil.ReadAll(f); else { return err }
// continue processing data
I don't want to open similar proposal for this one. Just an idea.
Based on the discussion above, the similarity to previously declined proposals, and the emoji voting, this is a likely decline. Leaving open for three weeks for final comments.
No further comments.
as per @ianlancetaylor: "Please let's not have a discussion about error handling in general on this issue. Please only discuss this specific proposal. Thanks."
This proposal is not about avoiding typing few keystrokes or shirking responsibilities for error handling or about making error handling in Go like any other language. It simply aims to use the compiler to reduce the mental workload of reading/reviewing error-heavy code. Error handling with this approach will remain as explicit and as boring as ever!
Author background
Proposal
I propose a new keyword
orelse
that is:Example
The example code in Russ Cox's paper[1] will look like this:
Rationale
The verbosity of Go's standard error handling approach is now a top concern for Go developers responding to the last annual survey. A more ergonomic approach should encourage adopting best practices of error handling and make code easier to read and maintain.
Compared to the current approach, I believe the proposed approach is:
Because
orelse
is not used for any other purpose, it would be easy for reviewers and linters to spot lack of error handling. And because it is semantically similar to anelse
block, it should be easy to learn and understand.Additional advantages include:
orelse
does not open a new scope when it is not desired making it more ergonomic and reducing the risk for variable shadowing as in this example of a widely used idiom:try
in the middle of expressions.it is backward compatible and does not prohibit those who prefer to use the current approach from continuing to use it.
it can handle the very rare situation when a function returns more than one error. The
oresle
block is invoked if any error is not nil.Costs and risks
[1] https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md