Proposal: Use blank identifier as zero value

332 views
Skip to first unread message

Huan Du

unread,
Dec 22, 2014, 9:06:50 AM12/22/14
to golan...@googlegroups.com
Zero value usually means "default value" or "useless value" in Go. For example, returning a nil if no error, or providing a nil or 0 in parameters as default value. However, there is no consistent way to set zero value, nor a way to express zero value semantics.


Feedback is highly appreciated. Personally, I really want this language feature in go. It can make my code cleaner.

Best regards,
- Huan

Ian Lance Taylor

unread,
Dec 22, 2014, 11:23:42 AM12/22/14
to Huan Du, golang-nuts
On Mon, Dec 22, 2014 at 6:06 AM, Huan Du <reald...@gmail.com> wrote:
>
> Zero value usually means "default value" or "useless value" in Go. For
> example, returning a nil if no error, or providing a nil or 0 in parameters
> as default value. However, there is no consistent way to set zero value, nor
> a way to express zero value semantics.
>
> I propose to use blank identifier as zero value. Here is full document.
>
> https://docs.google.com/a/huandu.me/document/d/1r0201KipyjKAQeIBOcDuF4jNmQzahLZAmYhfCD_R-c4/edit?usp=sharing

Thanks. A similar proposal has been made at least three times before:

https://groups.google.com/d/msg/golang-nuts/VXWNJQFCgts/V2ED_W_tCdEJ
https://groups.google.com/d/msg/golang-dev/iAysKGpniLw/qSbtBUx4-sMJ
https://groups.google.com/d/msg/golang-nuts/kBOnfs3a2tU/YxTuqMLhYckJ

I'm somewhat sympathetic to this feature but it's troubling that it
would make code like this valid:
f := float64(_) / _

Letting _ be a source as well as a sink means that it can appear in
all kinds of places where it may not be welcome. I don't find that to
be an improvement.

And, of course, this feature doesn't let you do anything you can't
already do.

Ian

Huan Du

unread,
Dec 22, 2014, 11:46:44 AM12/22/14
to Ian Lance Taylor, golang-nuts
I'm somewhat sympathetic to this feature but it's troubling that it
would make code like this valid:
>    f := float64(_) / _
I'm aware of this kind of ill formed code. I don't like it either. So at the end of the document, I propose to use blank identifier as zero value in very limited set of expressions/statements and disallow using "_" with any operator.

I think it's possible to define some simple rules to avoid abuse - just like what I proposed.

Best regards,
- Huan

Ian Lance Taylor

unread,
Dec 22, 2014, 12:04:31 PM12/22/14
to Huan Du, golang-nuts
On Mon, Dec 22, 2014 at 8:45 AM, Huan Du <reald...@gmail.com> wrote:
>> I'm somewhat sympathetic to this feature but it's troubling that it
> would make code like this valid:
>> f := float64(_) / _
> I'm aware of this kind of ill formed code. I don't like it either. So at the
> end of the document, I propose to use blank identifier as zero value in very
> limited set of expressions/statements and disallow using "_" with any
> operator.
>
> I think it's possible to define some simple rules to avoid abuse - just like
> what I proposed.

Yes, but then I would describe it as non-orthogonal. It introduces a
totally new concept: the areas of Go where _ is permitted. That is a
comprehension cost--something else that people need to understand when
writing Go code. I don't think that is a good thing. I think that if
this is introduced it needs to be the same as nil: it's OK anywhere
that the type can be inferred. It's already annoying that we need
special cases for nil in the spec.

Ian

adon...@google.com

unread,
Dec 22, 2014, 12:50:45 PM12/22/14
to golan...@googlegroups.com
On Monday, 22 December 2014 09:06:50 UTC-5, Huan Du wrote:
Zero value usually means "default value" or "useless value" in Go. For example, returning a nil if no error, or providing a nil or 0 in parameters

There is in fact a consistent way to obtain the zero value of any type:

var x T
x = *new(T)

Of course, it's ugly, and gc doesn't generate particularly good code for it (though go/ssa does, and I would guess gccgo does do, being SSA-based).  It's too bad the syntax isn't nicer, but it's not really too bad.

atd...@gmail.com

unread,
Dec 22, 2014, 1:02:31 PM12/22/14
to golan...@googlegroups.com
Hi Huan,

The below might help in some cases and should be cleaner if you need optional parameters for your functions.

(don't overdo it when your functional options are declared deep within a pkg hierarchy or it might become a little verbose, besides, you would have to switch from functions to methods and initialized objects. Otherwise, it is really nice, and you can use a lighter version w/o rollback of changes)
An example of how I personally do it in a simple case : http://play.golang.org/p/HBGd15cwYl

For return values, named return values are initially zeroed. So you could use that feature to your advantage

Also, it would be mostly used when you return "something" alongside an error value. But usually if there is an error, you don't really care about the value of the "something".

The way I see it, the language already covers most use cases.

Dmitri Shuralyov

unread,
Dec 22, 2014, 7:58:14 PM12/22/14
to golan...@googlegroups.com
Related to this, but an alternative approach: Quinn Slack has worked on a goimports-substitute tool that additionally to running goimports will also try to fill in missing returns with zero values, when you're returning an error. See:

https://github.com/sqs/goreturns

The idea is if your func returns (string, *http.Request, error) and you write `return err` and save, it'll fill in the missing zero values to make it `return "", nil, false`.

Huan Du

unread,
Dec 22, 2014, 10:48:47 PM12/22/14
to Ian Lance Taylor, golang-nuts
On Tue, Dec 23, 2014 at 1:04 AM, Ian Lance Taylor <ia...@golang.org> wrote:
Yes, but then I would describe it as non-orthogonal.  It introduces a
totally new concept: the areas of Go where _ is permitted.  That is a
comprehension cost--something else that people need to understand when
writing Go code.  I don't think that is a good thing.  I think that if
this is introduced it needs to be the same as nil: it's OK anywhere
that the type can be inferred.  It's already annoying that we need
special cases for nil in the spec.

OK. Make sense. Thank you.

On Tue, Dec 23, 2014 at 1:50 AM, <adon...@google.com> wrote:
There is in fact a consistent way to obtain the zero value of any type:

var x T
x = *new(T)

Ah. It's really an interesting hack. Thanks. I'm surprised that it even works with `interface{}`. Anyway, I'll avoid use it in real code definitely. :)

On Tue, Dec 23, 2014 at 2:02 AM, <atd...@gmail.com> wrote:
The below might help in some cases and should be cleaner if you need optional parameters for your functions.

Nice blog post. Thanks for your input.

On Tue, Dec 23, 2014 at 8:58 AM, Dmitri Shuralyov <shur...@gmail.com> wrote:
Related to this, but an alternative approach: Quinn Slack has worked on a goimports-substitute tool that additionally to running goimports will also try to fill in missing returns with zero values, when you're returning an error. See:

https://github.com/sqs/goreturns
 
You remind me that I can write a pre-compile tool to convert "_" to proper zero value without having any language change. Thanks.

Best regards,
- Huan
Reply all
Reply to author
Forward
0 new messages