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.

Reply via email to