Blog: Announcing the 2020 Go Developer Survey

204 views
Skip to first unread message

Andrew

unread,
Oct 22, 2020, 4:18:19 PM10/22/20
to golang-nuts

I've finished the survey but want to add this:
Go can add something for library author to "differentiate if a value was set or not internally", so that we can use plain Go type in the library.

Here is a link to the problem:

Thanks,
Andrew

Ian Lance Taylor

unread,
Oct 22, 2020, 6:18:53 PM10/22/20
to Andrew, golang-nuts
On Thu, Oct 22, 2020 at 1:19 PM Andrew <angan...@gmail.com> wrote:
>
> I've finished the survey but want to add this:
> Go can add something for library author to "differentiate if a value was set or not internally", so that we can use plain Go type in the library.
>
> Here is a link to the problem:
> https://github.com/mxschmitt/playwright-go/issues/49

Go does have a way: use a pointer, as that code is doing. Or you
could use a separate field to record whether the value is set. Or you
declare a type that uses two bools, and use that. And no doubt there
are other ways to do it.

So there are several possible approaches. I'm guessing you want one
that is more implicit, but as a general guideline Go tends to prefer
explicit code.

Ian

Jesper Louis Andersen

unread,
Oct 23, 2020, 7:15:14 AM10/23/20
to Ian Lance Taylor, Andrew, golang-nuts
On Fri, Oct 23, 2020 at 12:17 AM Ian Lance Taylor <ia...@golang.org> wrote:
So there are several possible approaches.  I'm guessing you want one
that is more implicit, but as a general guideline Go tends to prefer
explicit code.


I don't think there is a good implicit approach to this problem. If you have a value that is optional, it has to be modeled as such in your system. The `*bool` representation is precise: `nil` maps to the bottom of the domain, and `true`/`false` maps to the values of the domain. The only way to work with such a type is to match on it to determine if the pointer is nil, followed by inspection of the boolean value. Generally, optional values need somewhere in the program where they are scrutinized, and you can't avoid that scrutiny. You can try to hide it with some clever implicit construction, but that is very likely to lead to subtle errors in programs. People might want to treat `nil` as an exception case, but it really isn't. It is a value like any other value, and should be treated as such in the program.

The approach taken by e.g., OCaml is that there is no `nil` in the language at all. Rather, there is a `'a ref` type, but that cannot be initialized to be `nil`. It always references something valid. You can then mint your own `nil` by means of an option type:

type 'a option = None | Some of 'a

However, the underlying representation is much akin to that of a typical pointer value. What has this gained us? Well, we can now create

type 'a option2 = None2 | Some2 of 'a

for instance. This type is *different* from the first one, yet has the same underlying representation. Thus, we can avoid a problem in the Go `*bool` solution: namely conflation of pointer representations with optional values; we simply mint a new type. I think this is more explicit and more precise in representation. And it's solution would work well for the originally proposed case.

As an aside, this leads to an important design point: if pointers are used as optional values (and not for the sake of sharing/optimization) stripping away the pointer often leads to code that is easier to work with since you avoid that pesky nil-check all over the place and can do with it in one place. Also, the astute reader might have caught on to the fact that the same observation holds true for error values, which in OCaml are defined as:

type 'a err = Err of 'a
type ('a, 'b) result = Err of 'a | Ok of 'b

If we now recognize there is a unit type with one inhabitant, you can see that an `'a option` is really just a `(unit, 'b) result`. That is, there is a good type-theoretic reason for your observation.





--
J.

Marcin Romaszewicz

unread,
Oct 23, 2020, 12:16:32 PM10/23/20
to Jesper Louis Andersen, Ian Lance Taylor, Andrew, golang-nuts
A concrete example of an "Optional" implementation in present in the sql package:

In SQL, it's common to have "null" values be distinct from zero values, so the DB package has a struct with the value and a flag whether the value was present.

As others have said, you can already build this, it's just not part of built in language syntax.

-- Marcin

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAGrdgiWjsL-hyp3%2Bch8aRaHFxiFqZekbcHPVcftV7SpXLMiCeQ%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages