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: "?" as "!= nil" #32845

Closed
kybin opened this issue Jun 28, 2019 · 19 comments
Closed

proposal: "?" as "!= nil" #32845

kybin opened this issue Jun 28, 2019 · 19 comments
Labels
error-handling Language & library change proposals that are about error handling. FrozenDueToAge LanguageChange Suggested changes to the Go language Proposal v2 An incompatible library change
Milestone

Comments

@kybin
Copy link
Contributor

kybin commented Jun 28, 2019

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.

@gopherbot gopherbot added this to the Proposal milestone Jun 28, 2019
@integrii
Copy link

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.

@mccolljr
Copy link

mccolljr commented Jun 28, 2019

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.

@networkimprov
Copy link

I think you overlooked #32611

@JAicewizard
Copy link

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.

@rsc
Copy link
Contributor

rsc commented Jul 2, 2019

@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.

@rsc
Copy link
Contributor

rsc commented Jul 2, 2019

@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.

@ianlancetaylor ianlancetaylor added v2 An incompatible library change LanguageChange Suggested changes to the Go language labels Jul 3, 2019
@fasknifer
Copy link

fasknifer commented Jul 6, 2019

err? {
    return err
}

'?' already have meaning of 'if'

@ianlancetaylor
Copy link
Contributor

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.

@tandr
Copy link

tandr commented Jul 19, 2019

@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.

@ianlancetaylor
Copy link
Contributor

@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.

@tandr
Copy link

tandr commented Jul 19, 2019

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.

@ianlancetaylor
Copy link
Contributor

ianlancetaylor commented Jul 19, 2019

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.

@donaldnevermore
Copy link

I think ? as != nil doesn't help and it doesn't touch the essential of the error handling problem.

@griesemer
Copy link
Contributor

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
}

@ianlancetaylor
Copy link
Contributor

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

@tandr
Copy link

tandr commented Jul 30, 2019

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.

@ianlancetaylor
Copy link
Contributor

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.

@tandr
Copy link

tandr commented Jul 30, 2019

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).

@tandr
Copy link

tandr commented Sep 13, 2019

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 :) )

@bradfitz bradfitz added the error-handling Language & library change proposals that are about error handling. label Oct 29, 2019
@golang golang locked and limited conversation to collaborators Oct 28, 2020
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 Suggested changes to the Go language Proposal v2 An incompatible library change
Projects
None yet
Development

No branches or pull requests