Other places where Go relies on every type having a zero value:

    // Making slices with non-zero length.
    s := make([]*int, 10)

    // Reslicing a slice beyond its length.
    s := make([]*int, 0, 10)[:10]

    // Eliding fields from a composite literal.
    p := struct { x: int; y: *int } { x: 5 }
    s := []*int { 10: new(int) }

    // Initializing an array programmatically.
    var arr [10]*int
    for i := range arr { ... }

    // Accessing a non-existent map entry.
    v := m["non existent"]

    // Reading from a closed channel.
    v := <-ch

    // Comma-ok.
    // Without zero values, the type of `v` is in each case
    // something like `ok ? *int : uninitialized`.
    v, ok := m["string"]
    v, ok := i.(*int)
    v, ok := <-ch


On Tue, Aug 22, 2017 at 8:59 AM <gurpar...@gmail.com> wrote:

> I would like to echo on Tong Sun's suggestion here. I know his isn't an
> "experience report" per se, but a suggestion worth building on, for those
> who're wishful of optionals in Go.
>
> The case mentioned might be immediately solvable by just using a pointer
> to the variable, which gives you the ability to assign nil (json null) to
> it. However, *T is *not* syntactic sugar for Optional<T>. Pointers come
> across as "just as good as optionals" when needed because we don't have
> another [built-in] option. Not to mention, pointers have more than
> nil-assignability to them.
>
> I understand that we can just write a generic generator for Optional<T>
> for whatever type we want an optional wrapper for. This is something I've
> always done when absolutely needed (most of the time with proto3 Protobuf).
>
> func main() {
>     msg := pboptional.NewString()
>
>     fmt.Println("msg:", msg).        // => msg: nil
>
>     msg.From("hello world")
>
>     fmt.Println("msg:", msg)         // => msg: Optional("hello world")
>
>     if msg, ok := msg.Unwrap(); ok {
>         // some
>         fmt.Println("msg:", msg)     // => msg: hello world
>     } else {
>         // none
>         fmt.Println("msg is nil")
>     }
> }
>
> There are obvious advantages to using optionals, including safely defining
> variable. However, on the contrary, Go is currently, and by-design so, not
> in the best shape to adopt optional types. For optionals to be a viable in
> core, non-optionals would have to (?) guarantee a value (and not just
> assumed zero-value when left uninitialized). This is for the compiler to
> deliver the type-safety promise of optionals *and* non-optionals. In
> other words, it means that we would have to not allow uninitialized types
> to be zero-value. I mean, what good is supporting optional types, if the
> non-optionals don't require you to set their values?
>
> Consider this currently valid Go code:
>
> func getAge() (int, error) {
>     var age int
>     return age, errors.New("ERR") // age is assumed zero-value
> }
>
> func main() {
>     age, err := getAge() // => 0, ERR
> }
>
> With optionals implemented (how I'm imagining), this would become:
>
> // uninitialized non-optional should not compile
> // i.e. don't assume zero-value
> func getAge() (int, error) {
>     var age int
>     return age, errors.New("ERR") // => compile error: variable age is
> not initialized
> }
>
> // this should work instead
> func getAge() (int?, error) {
>     var age int?
>     return nil, errors.New("ERR")
> }
>
> func main() {
>     age, err := getAge() // => Optional(nil), ERR
> }
>
> But every method that also returns an error, should not necessarily have
> an accompanied optional type, like `(int?, error)`. There's so much in Go
> that can be nil (or nil like zero-values), and isn't necessarily fit to be
> considered optional, like nil interfaces and pointers.
>
> We're also going to have to reconsider the phrase "errors are just values"
> if we want to pair non-optional types with error in the return types. Take
> the following suggestion (inspired from Swift):
>
> func getAge() (int, throws error) {
>     var age int
>     throw errors.New("ERR")
>     // we're not returning anything and it compiles
>     // i.e. throw *is* return but only for error
> }
>
> func main() {
>     age := try getAge() // => panic("ERR")
> }
>
> func main() {
>     // although getAge() returns a non-optional, it
>     // gets is automatically wrapped in an optional
>     // when using `try?`.
>     //
>     // basically we're trading error for nil value.
>     age := try? getAge() // => Optional(nil)
> }
>
> func main() {
>     // this is the graceful way to get non-optional result
>     // and handle error, if any.
>     try {
>         age := getAge()
>     } catch error {
>         fmt.Println(err.Error()) // => ERR
>     }
> }
>
> Therefore, if considered, optionals would be a *huge* undertaking to
> implement (and practice) in Go source, while also delivering the promise
> optionals bring.
>
> Let me know if you have a better syntax/suggestion than try catch blocks
> (for returning only an error; no zero-values for non-optionals).
>
> I think an ideal first step would be the community blessing and adopting
> en masse some Optional<T> "generator". Second step would be to vouch for
> generics with this use case. And then implement an actual generic like
> `type Optional<T> struct { Value T; HasValue bool }`. And then perhaps, as
> the fourth or so step, we may shape our coding practices to better
> understand how all this could be practiced in Go source itself.
>
> --
> Gurpartap Singh
> https://twitter.com/Gurpartap
>
> On Saturday, August 19, 2017 at 8:35:34 PM UTC+5:30, Tong Sun wrote:
>>
>> Suggesting C# type syntax like "int*?*" so as to take nil as valid
>> value.
>>
>> Currently:
>>
>> var i int
>> i = nil
>>
>> will give:
>>
>> cannot use nil as type int in assignment
>>
>> However, more and more people are using json to transport data, and there
>> will be times that json may be invalid. I.e., the "int" type has 'null' as
>> input.
>>
>> This is causing tremendous problems for me so far, as I have to jump over
>> the hoops to deal with them.
>> In C#, just by adding a "?" to the end of the type solves the problem.
>>
>> Please consider.
>>
>>
>>
>> --
> 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+unsubscr...@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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to