Re: [go-nuts] Re: Go 2 suggestion - Types like "int?"
Relevant Tweet: https://twitter.com/casio_juarez/status/900374362401914881 On Wednesday, August 23, 2017 at 1:42:07 AM UTC+5:30, Joe Tsai wrote: > > What you are asking for is captured in https://golang.org/issue/7054 > > On Tuesday, August 22, 2017 at 12:28:41 PM UTC-7, Steven Blenkinsop wrote: >> >> 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 AMwrote: >> >>> 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. 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 >>> 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
Re: [go-nuts] Re: Go 2 suggestion - Types like "int?"
What you are asking for is captured in https://golang.org/issue/7054 On Tuesday, August 22, 2017 at 12:28:41 PM UTC-7, Steven Blenkinsop wrote: > > 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 AMwrote: > >> 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. 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 >> 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 { >>
Re: [go-nuts] Re: Go 2 suggestion - Types like "int?"
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 AMwrote: > 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. 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 > 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