samber / lo

💥 A Lodash-style Go library based on Go 1.18+ Generics (map, filter, contains, find...)
https://pkg.go.dev/github.com/samber/lo
MIT License
16.57k stars 758 forks source link

Add support for optional chaining #107

Open samber opened 2 years ago

samber commented 2 years ago

Some languages like Typescript or Swift offer a very cool syntactic sugar a?.b?.c?.d?.e.

In Go, we need to write a condition similar to: a != nil && a.b != nil && a.b.c != nil.

I create this issue for discussing a new helper.

In PR #106, I suggest an implementation called Safe:

type a struct {
    foo *string
}
type b struct {
    a *a
}
type c struct {
    b *b
}

v := &c{
    b: &b{
        a: nil,
    },
}

foo, ok := lo.Safe(func() string { return *v.b.a.foo })
// "", false

Calling *v.b.a.foo will panic, but this nil pointer error will be caught by lo.Safe. Other exception won't be caught.

This implementation is much more "typesafe" than something like lo.Safe(a, ".b.c.d")

WDYT?

wirekang commented 2 years ago

Safe is very good function. But can we implement real optional chaining without modifing Go Compiler? I mean, if a.b.c panics because a.b is nil, the 'Optional Chaining Function' should returns a. But how can we get information of a?

CorentinClabaut commented 1 year ago

This looks nice. It's verbose, but without a language update it looks like that's the best option. I was thinking, it might be helpful to also have a function with a default value in case of panic like func SafeOr[T any](cb func() T, fallback T) T WDYT?

renom commented 1 year ago

Catching out of bounds error would make sense too