Hi, this proposal is somewhat related to current error handling proposal debate.
I think many people want to keep current explicit error handling,
but many other people don't like boilerplate.
If we care one aspect, another aspect is sacrificed.
So I thought simple change everyone can understand,
not touching any other thing but reduce current boilerplate a bit.
How about introduce a new symbol ?
to check the pointer is nil or non-nil?
I mean we usually code like this.
if err != nil {
return err
}
with this proposal we can code like this.
if err? {
return err
}
I know this doesn't reduce boilerplate much. (6 characters) But personally != nil
is quite hard to type. And pointers are everywhere that means we type != nil
repeatedly. It's tiresome a little.
Currently we don't check a bool variable explicitly in if statement.
I mean we don't do
if ok == true {
...
}
but do
if ok {
...
}
````
With this proposal, we will not use
if err != nil {
...
}
but instead use
if err? {
...
}
and nil check will be
if !err? {
...
}
This small saving of space can be used for one-liner error handling. (I know gofmt don't permit this for now)
if err? { return err }
```
I don't want arguing that this is better than other proposals, but seems interesting so I want to share.
Thank you.
It's one of the better ideas I've seen here, and I don't hate it. I still think it adds a little obscurity where we otherwise had more explicit purpose. Explicit is better than implicit.
I like the intent of this proposal but I'm not a fan of the ?
syntax. ?
would be a new operator, one that go has explicitly avoided up to this point. Perhaps we could adopt a bit of existing syntax that would fail to compile, and ascribe special meaning that is obvious from the reading of the code?
package main
func main() {
var e error
var v *struct{ int }
if nil(e) {
// e is nil
}
if nil(v) {
// v is nil pointer
}
}
The above checks (nil(e)
and nil(v)
) will currently fail due to "use of untyped nil", but they could instead be treated as boolean checks of e == nil
and v == nil
respectively. You could negate these using !nil(e)
or !nil(v)
respectively.
This requires no new syntax, reads clearly (literally "if nil (expr)" or "if not nil (expr)" when paired with !
), and decreases the verbosity of nil checks, even if by a little bit.
I think you overlooked #32611
could we extent this to just this?
if v {
}
v will return true if the value is non-zero. This will be compatible with the current use of if v{}
where v is a boolean set to true. This would be a backwards-compatible spec change for GO2 that will resolve some boiler plate for error handling as well.
@JAicewizard, we won't do if v
for arbitrary types of v
(like C and C++), because then if "false" { panic("false is true") }
would panic instead of being rejected by the compiler. (We've seen mistakes like this in large C++ programs, though not quite so obvious.)
It is a feature that the compiler complains when you forget to write half the comparison.
@kybin, this is an interesting idea, thanks. Not sure about the readability of !err?
though.
There are significant fixed costs to any language change: updating tools, teaching everyone the new thing, updating tools, deciding when it is appropriate, teaching everyone those guidelines, and so on. The change needs to bring benefits that pay for those costs. Some people are saying that try does not bring enough benefits to outweigh these costs, but err?
carries even fewer benefits: just saving a few characters on a single line, and now having two different ways to write that check.
err? {
return err
}
'?' already have meaning of 'if'
There are only a few printable ASCII characters that Go doesn't use today. To me it doesn't seem worth using one of them just to avoid writing != nil
.
@rsc and @ianlancetaylor
What if this is not a "just" non-equal to nil
comparison? What if this is a lets-fix-earlier-design escape route for interfaces to be safely checked for "has something"?
I vaguely remember we have had our part of learning curve with casting to error
, when I changed funcs that returned error
to something that returned our own interface that was supposed to wrap (or behave like) error
, but all these checks for != nil
blew up in my face a couple weeks later when we thought we returned nil
, but err != nil
failed (I did not know/think of wrap/unwrap at that time). I think what we have experienced is close to what https://dev.to/pauljlucas/go-tcha-when-nil--nil-hic explains.
This would make it compatible with Go 1 - code that does if err != nil
will continue to behave as it is today, code that does if err? {...
will behave "as expected".
PS.
still hopeful that we can get to somePointerToStruct?.field
one day... Last week I "had it" dealing with XML-schema based structs, where even a string
field is a pointer to string
, and you have to unwrap 4 levels down with if s != nil && s.ss1 != nil && s.ss1.sss2 != nil { // do something with s.ss1.sss2 }
I was voicing ?
checks with 2 slightly different behaviours in golang-nuts list, making me not an "independent party" for this one, so take it with a grain of salt.
@tandr I think you are referring to https://golang.org/doc/faq#nil_error . That is already a subtle distinction that confuses people new to Go. I would be concerned that treating ?
as subtly different from != nil
, as meaning something like "neither nil
nor containing a nil
pointer", would increase confusion rather than decreasing it.
Thanks Ian, this is exactly it.
Not having that "subtleness", or at least be able to distinguish and check for these cases would save me some of my now grey hair, it is unbelievable maddening behaviour. We have a code base that people come in and out ("oh, just add it to that component, Go is easy enough to pick up"). Every time when I review the code, I have to double check for this too. But I am not a compiler, I might miss it again.
I agree that it would be nice to smooth out that bump in Go understanding. There are some proposals to address it, such as my #22729. But I do not think that making the '?' proposed here be different from != nil
would be a good step forward. I think that would increase confusion rather than decreasing it.
I think ?
as != nil
doesn't help and it doesn't touch the essential of the error handling problem.
Just for the record: If err != nil
is too hard to read or type, it could always be replaced with something like E(err)
where E
is:
func E(err error) bool {
return err != nil
}
Replacing != nil
with ?
does not bring enough benefit to be worth the cost of a language change and the use of a currently unused character. Also !v?
is confusing.
-- for @golang/proposal-review
I think it feels like tear in the reading flow because we are just not used to it. And to nitpick - anything with just one letter is confusing without a context :)
Thanks for listening though. I am still of the opinion we can use ?
as a real question mark :), collapsing if obj, err := io.Open("bad"); err != nil { return nil, err }
into just obj := io.Open("bad")?
with some simple rules.
I am still of the opinion we can use ? as a real question mark :), collapsing if obj, err := io.Open("bad"); err != nil { return nil, err } into just obj := io.Open("bad")? with some simple rules.
@tandr Well, that proposal is not this proposal. It also at first glance seems quite similar to the rejected #32437.
Thank Ian. In a context of just checking for error - yes, you are absolutely right, it does cover same grounds.
(I guess my head is keep going in circles, wanting _an operator_ that could be used for so many checks - pointers (naked and typed), errors, return values that contains an error - that feels like I am getting a bit confused here. I need to switch gears, thanks for the reminder).
Linking https://github.com/tc39/proposal-optional-chaining as they have some discussion on it too.
(I am starting to think there is an information field in the universe, and we are all connected. I have not seen or read that paper before commenting in all these tickets 2 months ago. This is just creepy. Or we all follow what C# does :) )
Most helpful comment
I like the intent of this proposal but I'm not a fan of the
?
syntax.?
would be a new operator, one that go has explicitly avoided up to this point. Perhaps we could adopt a bit of existing syntax that would fail to compile, and ascribe special meaning that is obvious from the reading of the code?The above checks (
nil(e)
andnil(v)
) will currently fail due to "use of untyped nil", but they could instead be treated as boolean checks ofe == nil
andv == nil
respectively. You could negate these using!nil(e)
or!nil(v)
respectively.This requires no new syntax, reads clearly (literally "if nil (expr)" or "if not nil (expr)" when paired with
!
), and decreases the verbosity of nil checks, even if by a little bit.