FAQ
I was wondering when was the last time supporting typed unions (or variant
types, or sums, or algebraic types, etc) was considered. I understand that
this question is frequently asked <https://golang.org/doc/faq#variant_types>,
but searching the list doesn't reveal anything recent.

What may have changed recently is the introduction of oneof into the
protobuf spec. Oneof has only been around a little over a year, but it
appears in almost all new proto files I see inside Google, and in many old
ones too. Not only does it nicely fit into many designs, there have been
instances of substantial memory improvements.

So, does the adoption of this feature make it worth reconsidering
language-level support?

Not that anyone asked, but here's how I'd do it:

type MyUnion union {
   a int
   b int
   c string
}

var foo MyUnion // zero value has none set
foo.a = 42

switch f := foo {
   case a: // f has type int
   case b: // f has type int
   case c: // f has type string
   default: // f not declared
}

Under the covers, a union would be a struct with an integer tag and a C
union of the underlying fields. Switch would be the only way to read the
fields, to sidestep the "accessing the wrong field" problem.

Hunter

--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Ian Lance Taylor at Jun 12, 2015 at 9:14 pm

    On Fri, Jun 12, 2015 at 1:36 PM, Hunter Freyer wrote:
    I was wondering when was the last time supporting typed unions (or variant
    types, or sums, or algebraic types, etc) was considered. I understand that
    this question is frequently asked, but searching the list doesn't reveal
    anything recent.
    Probably about five years ago.

    What may have changed recently is the introduction of oneof into the
    protobuf spec. Oneof has only been around a little over a year, but it
    appears in almost all new proto files I see inside Google, and in many old
    ones too. Not only does it nicely fit into many designs, there have been
    instances of substantial memory improvements.

    So, does the adoption of this feature make it worth reconsidering
    language-level support?
    I don't personally find this feature persuasive by itself. This is
    not because oneof is not useful, but because 1) there are other
    approaches we can take; 2) the most important aspect of protobufs is
    how much space they take on the wire, and that is unaffected by the
    presence or absence of unions in Go.

    Not that anyone asked, but here's how I'd do it:

    type MyUnion union {
    a int
    b int
    c string
    }

    var foo MyUnion // zero value has none set
    foo.a = 42

    switch f := foo {
    case a: // f has type int
    case b: // f has type int
    case c: // f has type string
    default: // f not declared
    }

    Under the covers, a union would be a struct with an integer tag and a C
    union of the underlying fields. Switch would be the only way to read the
    fields, to sidestep the "accessing the wrong field" problem.
    This is almost exactly like a interface{}, except that the set of
    types of values that may be stored are restricted. So, for purposes
    of protobufs, why not use an interface{}?

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Hunter Freyer at Jun 12, 2015 at 9:31 pm

    On Fri, Jun 12, 2015 at 5:14 PM Ian Lance Taylor wrote:
    On Fri, Jun 12, 2015 at 1:36 PM, Hunter Freyer wrote:

    I was wondering when was the last time supporting typed unions (or variant
    types, or sums, or algebraic types, etc) was considered. I understand that
    this question is frequently asked, but searching the list doesn't reveal
    anything recent.
    Probably about five years ago.

    What may have changed recently is the introduction of oneof into the
    protobuf spec. Oneof has only been around a little over a year, but it
    appears in almost all new proto files I see inside Google, and in many old
    ones too. Not only does it nicely fit into many designs, there have been
    instances of substantial memory improvements.

    So, does the adoption of this feature make it worth reconsidering
    language-level support?
    I don't personally find this feature persuasive by itself. This is
    not because oneof is not useful, but because 1) there are other
    approaches we can take; 2) the most important aspect of protobufs is
    how much space they take on the wire, and that is unaffected by the
    presence or absence of unions in Go.
    Yeah, just to be clear, I bring up protobufs not because oneofs are
    particularly hard to use in Go (they're fine), but as an indication that
    unions might be a more compelling feature than was previously thought. The
    FAQ makes it sounds like the attitude is "yeah, we could probably do it,
    but would it actually help much?" I'd argue that oneof shows that if people
    could use unions in their regular structs as well, they would.

    Not that anyone asked, but here's how I'd do it:

    type MyUnion union {
    a int
    b int
    c string
    }

    var foo MyUnion // zero value has none set
    foo.a = 42

    switch f := foo {
    case a: // f has type int
    case b: // f has type int
    case c: // f has type string
    default: // f not declared
    }

    Under the covers, a union would be a struct with an integer tag and a C
    union of the underlying fields. Switch would be the only way to read the
    fields, to sidestep the "accessing the wrong field" problem.
    This is almost exactly like a interface{}, except that the set of
    types of values that may be stored are restricted. So, for purposes
    of protobufs, why not use an interface{}?

    Ian
    Basically because a union could have two fields of the same type with
    different meanings. My variable "foo" up there couldn't be interface{}
    without creating wrapper types for int, which seems backwards.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jun 12, 2015 at 11:03 pm

    On Fri, Jun 12, 2015 at 2:31 PM, Hunter Freyer wrote:
    On Fri, Jun 12, 2015 at 5:14 PM Ian Lance Taylor wrote:
    On Fri, Jun 12, 2015 at 1:36 PM, Hunter Freyer wrote:

    Not that anyone asked, but here's how I'd do it:

    type MyUnion union {
    a int
    b int
    c string
    }

    var foo MyUnion // zero value has none set
    foo.a = 42

    switch f := foo {
    case a: // f has type int
    case b: // f has type int
    case c: // f has type string
    default: // f not declared
    }

    Under the covers, a union would be a struct with an integer tag and a C
    union of the underlying fields. Switch would be the only way to read the
    fields, to sidestep the "accessing the wrong field" problem.
    This is almost exactly like a interface{}, except that the set of
    types of values that may be stored are restricted. So, for purposes
    of protobufs, why not use an interface{}?
    Basically because a union could have two fields of the same type with
    different meanings. My variable "foo" up there couldn't be interface{}
    without creating wrapper types for int, which seems backwards.
    "type AInt int" doesn't seem too horrible.

    To be clear, I completely agree that unions are useful. That's not
    the question. The question is whether it is worth adding a new
    concept to the language, given that the concept has a significant
    overlap with an existing concept.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Sokolov Yura at Jun 13, 2015 at 9:41 am
    Cause of change in go 1.4 "tagged union" gained sense again:

    - before small values (int, int64, float64 on 64bit machine) were stored in
    a value half of interface{}
    - now they are allocated separately.

    My fellow told that "generic" data interface (parsing msgpack - "binary
    json") becomes twice as slower in 1.4 compared to 1.3.

    I can understand, that uniform interface{} layout helps GC to scan heap
    faster. But may be there could be a compromise?

    суббота, 13 июня 2015 г., 2:03:17 UTC+3 пользователь Ian Lance Taylor
    написал:
    On Fri, Jun 12, 2015 at 2:31 PM, Hunter Freyer <y...@hjfreyer.com
    <javascript:>> wrote:
    On Fri, Jun 12, 2015 at 5:14 PM Ian Lance Taylor <ia...@golang.org
    <javascript:>> wrote:
    On Fri, Jun 12, 2015 at 1:36 PM, Hunter Freyer <y...@hjfreyer.com
    <javascript:>> wrote:
    Not that anyone asked, but here's how I'd do it:

    type MyUnion union {
    a int
    b int
    c string
    }

    var foo MyUnion // zero value has none set
    foo.a = 42

    switch f := foo {
    case a: // f has type int
    case b: // f has type int
    case c: // f has type string
    default: // f not declared
    }

    Under the covers, a union would be a struct with an integer tag and a
    C
    union of the underlying fields. Switch would be the only way to read
    the
    fields, to sidestep the "accessing the wrong field" problem.
    This is almost exactly like a interface{}, except that the set of
    types of values that may be stored are restricted. So, for purposes
    of protobufs, why not use an interface{}?
    Basically because a union could have two fields of the same type with
    different meanings. My variable "foo" up there couldn't be interface{}
    without creating wrapper types for int, which seems backwards.
    "type AInt int" doesn't seem too horrible.

    To be clear, I completely agree that unions are useful. That's not
    the question. The question is whether it is worth adding a new
    concept to the language, given that the concept has a significant
    overlap with an existing concept.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jun 13, 2015 at 8:07 pm

    On Sat, Jun 13, 2015 at 2:41 AM, Sokolov Yura wrote:
    Cause of change in go 1.4 "tagged union" gained sense again:

    - before small values (int, int64, float64 on 64bit machine) were stored in
    a value half of interface{}
    - now they are allocated separately.

    My fellow told that "generic" data interface (parsing msgpack - "binary
    json") becomes twice as slower in 1.4 compared to 1.3.

    I can understand, that uniform interface{} layout helps GC to scan heap
    faster. But may be there could be a compromise?
    Changing the language to address an implementation performance issue
    is not completely impossible. But it's definitely a last resort.

    The Go 1.5 GC is quite a bit faster, and many programs run faster on
    1.5 than on 1.4. Let's not give up too soon.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Hunter Freyer at Jun 13, 2015 at 8:43 pm

    On Fri, Jun 12, 2015 at 7:03 PM Ian Lance Taylor wrote:
    On Fri, Jun 12, 2015 at 2:31 PM, Hunter Freyer wrote:
    On Fri, Jun 12, 2015 at 5:14 PM Ian Lance Taylor wrote:
    On Fri, Jun 12, 2015 at 1:36 PM, Hunter Freyer wrote:

    Not that anyone asked, but here's how I'd do it:

    type MyUnion union {
    a int
    b int
    c string
    }

    var foo MyUnion // zero value has none set
    foo.a = 42

    switch f := foo {
    case a: // f has type int
    case b: // f has type int
    case c: // f has type string
    default: // f not declared
    }

    Under the covers, a union would be a struct with an integer tag and a
    C
    union of the underlying fields. Switch would be the only way to read
    the
    fields, to sidestep the "accessing the wrong field" problem.
    This is almost exactly like a interface{}, except that the set of
    types of values that may be stored are restricted. So, for purposes
    of protobufs, why not use an interface{}?
    Basically because a union could have two fields of the same type with
    different meanings. My variable "foo" up there couldn't be interface{}
    without creating wrapper types for int, which seems backwards.
    "type AInt int" doesn't seem too horrible.

    To be clear, I completely agree that unions are useful. That's not
    the question. The question is whether it is worth adding a new
    concept to the language, given that the concept has a significant
    overlap with an existing concept.
    Well, let's take a concrete example:
    https://github.com/GoogleCloudPlatform/kubernetes/blob/master/pkg/api/types.go

    This file is loaded with conceptual union types. Things like VolumeSource
    could be turned from a struct into a union, and all that would change would
    be a bit more safety, and a bit improved memory usage. Using the code would
    be a little simpler, because you'd avoid silly code like this:
    https://github.com/GoogleCloudPlatform/kubernetes/blob/d7f7d84a5ed20396691ac725aec668cee3e17c4b/pkg/api/validation/validation.go#L306

    Nothing groundbreaking, but I'd argue a win.

    The interface{} solution wouldn't work at all here because JSON
    serialization wouldn't work right. But even if these things never got
    serialized, I think replacing VolumeSource with interface{} and commenting
    all the types it might be would not improve the situation. I think it'd
    hurt readability and expose the coders to unnecessary bugs, like trying to
    set an EmptyDir on a PersistentVolumeSource when it can actually only be a
    part of a VolumeSource.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jun 13, 2015 at 8:51 pm

    On Sat, Jun 13, 2015 at 1:43 PM, Hunter Freyer wrote:
    Well, let's take a concrete example:
    https://github.com/GoogleCloudPlatform/kubernetes/blob/master/pkg/api/types.go

    This file is loaded with conceptual union types. Things like VolumeSource
    could be turned from a struct into a union, and all that would change would
    be a bit more safety, and a bit improved memory usage. Using the code would
    be a little simpler, because you'd avoid silly code like this:
    https://github.com/GoogleCloudPlatform/kubernetes/blob/d7f7d84a5ed20396691ac725aec668cee3e17c4b/pkg/api/validation/validation.go#L306

    Nothing groundbreaking, but I'd argue a win.
    To be clear, I completely agree that unions are useful. That's not
    the question. The question is whether it is worth adding a new
    concept to the language, given that the concept has a significant
    overlap with an existing concept.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Hunter Freyer at Jun 13, 2015 at 9:07 pm

    On Sat, Jun 13, 2015 at 4:51 PM Ian Lance Taylor wrote:
    On Sat, Jun 13, 2015 at 1:43 PM, Hunter Freyer wrote:

    Well, let's take a concrete example:
    https://github.com/GoogleCloudPlatform/kubernetes/blob/master/pkg/api/types.go
    This file is loaded with conceptual union types. Things like VolumeSource
    could be turned from a struct into a union, and all that would change would
    be a bit more safety, and a bit improved memory usage. Using the code would
    be a little simpler, because you'd avoid silly code like this:
    https://github.com/GoogleCloudPlatform/kubernetes/blob/d7f7d84a5ed20396691ac725aec668cee3e17c4b/pkg/api/validation/validation.go#L306
    Nothing groundbreaking, but I'd argue a win.
    To be clear, I completely agree that unions are useful. That's not
    the question. The question is whether it is worth adding a new
    concept to the language, given that the concept has a significant
    overlap with an existing concept.
    Right, the next paragraph after that argued that the existing concept is
    ill suited to this use case.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Axel Wagner at Jun 13, 2015 at 9:28 pm

    Hunter Freyer writes:
    Right, the next paragraph after that argued that the existing concept is
    ill suited to this use case.
    The argument wasn't, that both serve the same usecases, or that the
    usecases of one are contained in the other, but that there is overlap
    (this overlap is, what you referred to as "the interface{} solution").

    go strives for orthotogonal language features. Orthotogonality means, in
    this context, that there should ideally be no overlap between different
    language features at all. That way, you get the maximum expressive power
    with the least complexity and cognitive overhead. I like that.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jun 14, 2015 at 1:51 am

    On Sat, Jun 13, 2015 at 2:07 PM, Hunter Freyer wrote:
    On Sat, Jun 13, 2015 at 4:51 PM Ian Lance Taylor wrote:
    On Sat, Jun 13, 2015 at 1:43 PM, Hunter Freyer wrote:

    Well, let's take a concrete example:

    https://github.com/GoogleCloudPlatform/kubernetes/blob/master/pkg/api/types.go

    This file is loaded with conceptual union types. Things like
    VolumeSource
    could be turned from a struct into a union, and all that would change
    would
    be a bit more safety, and a bit improved memory usage. Using the code
    would
    be a little simpler, because you'd avoid silly code like this:

    https://github.com/GoogleCloudPlatform/kubernetes/blob/d7f7d84a5ed20396691ac725aec668cee3e17c4b/pkg/api/validation/validation.go#L306

    Nothing groundbreaking, but I'd argue a win.
    To be clear, I completely agree that unions are useful. That's not
    the question. The question is whether it is worth adding a new
    concept to the language, given that the concept has a significant
    overlap with an existing concept.
    Right, the next paragraph after that argued that the existing concept is ill
    suited to this use case.
    Yes, but that doesn't address the point I'm trying to make. You don't
    need to explain why unions are useful, and you don't need to explain
    that they will permit you to do things that you can't easily do today.
    I believe that already.

    Every change to the language carries a cost: every Go programmer, and
    every Go tool, has to learn what it means and how to use it. You have
    to explain why that cost is worth it. In this case, there is the
    extra cost that unions are a lot like interfaces, so people will have
    to learn the relatively subtle differences between them.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Henry Adi Sumarto at Jun 14, 2015 at 2:22 am
    Has the original poster considered using a builder pattern that will build the appropriate type depending on the parameters? All the return types implement a common interface. I think it works a lot like union. The difference is that in the case of union the compiler does the work for us.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Michael Jones at Jun 14, 2015 at 2:27 pm
    I brought the idea up a few years ago…
    https://groups.google.com/forum/#!searchin/golang-nuts/union/golang-nuts/VZ0rY12nzSM/ZV-4-sQ2R_IJ


    Michael Jones, CEO • michael@wearality.com • +1 650 656-6989
    Wearality Corporation • 289 S. San Antonio Road • Los Altos, CA 94022
    On Jun 13, 2015, at 7:21 PM, Henry Adi Sumarto wrote:

    Has the original poster considered using a builder pattern that will build the appropriate type depending on the parameters? All the return types implement a common interface. I think it works a lot like union. The difference is that in the case of union the compiler does the work for us.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Manlio Perillo at Jun 14, 2015 at 4:08 pm
    Il giorno domenica 14 giugno 2015 03:51:20 UTC+2, Ian Lance Taylor ha
    scritto:
    On Sat, Jun 13, 2015 at 2:07 PM, Hunter Freyer <y...@hjfreyer.com
    <javascript:>> wrote:
    [...]
    Yes, but that doesn't address the point I'm trying to make. You don't
    need to explain why unions are useful, and you don't need to explain
    that they will permit you to do things that you can't easily do today.
    I believe that already.

    Every change to the language carries a cost: every Go programmer, and
    every Go tool, has to learn what it means and how to use it. You have
    to explain why that cost is worth it. In this case, there is the
    extra cost that unions are a lot like interfaces, so people will have
    to learn the relatively subtle differences between them.
    IMHO, unions *does not* look like interface.
    The only thing they have in common is the use of the type switch to get the
    actual type stored.


    Regards Manlio

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Ian Lance Taylor at Jun 15, 2015 at 3:10 am

    On Sun, Jun 14, 2015 at 9:08 AM, Manlio Perillo wrote:
    Il giorno domenica 14 giugno 2015 03:51:20 UTC+2, Ian Lance Taylor ha
    scritto:
    On Sat, Jun 13, 2015 at 2:07 PM, Hunter Freyer wrote:

    Yes, but that doesn't address the point I'm trying to make. You don't
    need to explain why unions are useful, and you don't need to explain
    that they will permit you to do things that you can't easily do today.
    I believe that already.

    Every change to the language carries a cost: every Go programmer, and
    every Go tool, has to learn what it means and how to use it. You have
    to explain why that cost is worth it. In this case, there is the
    extra cost that unions are a lot like interfaces, so people will have
    to learn the relatively subtle differences between them.
    IMHO, unions *does not* look like interface.
    The only thing they have in common is the use of the type switch to get the
    actual type stored.
    In both cases you have a value and a tag. In both cases you can
    assign any value that meets certain criteria. In both cases you have
    to use a type assertion or a type switch to extract the value.

    Most importantly, any place you would use an union, you can define a
    few more types and use an interface instead. The interface is more
    awkward to use, especially if you want to make it as type-safe as the
    union. The interface is also in some cases less memory efficient.
    But the interface gives you all the same functionality. That is what
    I mean when I say that the differences are subtle.

    Ian

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Hunter Freyer at Jun 18, 2015 at 3:29 pm
    I mostly buy that.

    One interesting use case associated with union types is pattern matching.
    Like union types, I've never seen it implemented in an imperative language,
    but it could fit reasonably naturally into go (a generalization of switch).
    I'll mull that over :)
    On Sun, Jun 14, 2015 at 11:10 PM Ian Lance Taylor wrote:

    On Sun, Jun 14, 2015 at 9:08 AM, Manlio Perillo
    wrote:
    Il giorno domenica 14 giugno 2015 03:51:20 UTC+2, Ian Lance Taylor ha
    scritto:
    On Sat, Jun 13, 2015 at 2:07 PM, Hunter Freyer wrote:

    Yes, but that doesn't address the point I'm trying to make. You don't
    need to explain why unions are useful, and you don't need to explain
    that they will permit you to do things that you can't easily do today.
    I believe that already.

    Every change to the language carries a cost: every Go programmer, and
    every Go tool, has to learn what it means and how to use it. You have
    to explain why that cost is worth it. In this case, there is the
    extra cost that unions are a lot like interfaces, so people will have
    to learn the relatively subtle differences between them.
    IMHO, unions *does not* look like interface.
    The only thing they have in common is the use of the type switch to get the
    actual type stored.
    In both cases you have a value and a tag. In both cases you can
    assign any value that meets certain criteria. In both cases you have
    to use a type assertion or a type switch to extract the value.

    Most importantly, any place you would use an union, you can define a
    few more types and use an interface instead. The interface is more
    awkward to use, especially if you want to make it as type-safe as the
    union. The interface is also in some cases less memory efficient.
    But the interface gives you all the same functionality. That is what
    I mean when I say that the differences are subtle.

    Ian
    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Henry Adi Sumarto at Jun 15, 2015 at 10:04 am
    Here is what I meant to say..

    https://play.golang.org/p/TCuzwVcji6

    I wonder whether this solves the OP's requirements. I do think it works a
    lot like union, except that it is a bit lengthy.

    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Manlio Perillo at Jun 13, 2015 at 4:08 pm
    Il giorno venerdì 12 giugno 2015 23:01:57 UTC+2, Hunter Freyer ha scritto:
    I was wondering when was the last time supporting typed unions (or variant
    types, or sums, or algebraic types, etc) was considered. I understand that
    this question is frequently asked
    <https://golang.org/doc/faq#variant_types>, but searching the list
    doesn't reveal anything recent.

    What may have changed recently is the introduction of oneof into the
    protobuf spec. Oneof has only been around a little over a year, but it
    appears in almost all new proto files I see inside Google, and in many old
    ones too. Not only does it nicely fit into many designs, there have been
    instances of substantial memory improvements.

    So, does the adoption of this feature make it worth reconsidering
    language-level support?

    Not that anyone asked, but here's how I'd do it:
    type MyUnion union {
    a int
    b int
    c string
    }

    var foo MyUnion // zero value has none set
    IMHO, the empty union has all its members set to the specific zero value.

    foo.a // == 0
    foo.b // == 0
    foo.c // == ""

    foo.a = 42
    Once you set a member, getting any other member will cause an error.

    switch f := foo {
    case a: // f has type int
    case b: // f has type int
    case c: // f has type string
    default: // f not declared
    }
    I would write this to be the same as the type switch for the interface type.

    The **big** difference between an union and an interface type is that a
    value in the interface type is boxed.
    In the past there was an optimization for small types, but this has been
    removed, AFAIK.

    Consider the following code from a scanner.

         type Token interface{}

         func (s *Scanner) Next() Token {
             ...
         }

         Token tok;
         ...
         tok = s.Next()

    This code has two problem:

    1) The Token type is too "wide"
    2) Returning a new token requires some memory allocation


    Here is the alternate code using the union type

         type Token union {
             ...
         }

         func (s *Scanner) Next(tok *Token) {
            ...
         }

         var Token tok;
         ....
         s.Next(&tok);


    Here the same variable is reused to read all tokens; this is what happens
    when reading
    a buffer from a Reader.


    Regards Manlio


    --
    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+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedJun 12, '15 at 9:01p
activeJun 18, '15 at 3:29p
posts18
users7
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase