top | item 29581968

(no title)

hmmdar | 4 years ago

Another way to do `Option` without pointers could be similar to the following with a struct with two members.

  type Option[T any] struct {
      v T
      isSet bool
  }
  
  func NewOption[T any](v T) Option[T] {
      return Option[T]{
          v: v,
          isSet: true,
      }
  }
  
  func (o Option[T]) Get() (v T) {
      if !o.isSet {
          return v
      }
      return o.v
  }
  
  func (o Option[T]) IsSet() bool { return o.isSet }

With this pattern you're able to use `Option` as a value without pointers.

  var o Option[int32]
  
  o = NewOption(int32(1))
  
  fmt.Println("value:", o.Get())
  fmt.Println("is set:", o.IsSet())
Alternative separate `Get` and `IsSet` methods, is to combine them into one, similar to map look up pattern.

  func (o Option[T]) Get() (v T, isSet bool) {
      if !o.isSet {
          return v, false
      }
      return o.v, true
  }
  
  var o Options[int32]
  v, ok := o.Get() // zero, false
  
  o = NewOption(int32(1))
  v, ok = o.Get() // 1, true

discuss

order

iambvk|4 years ago

I agree with `Get` returning `(T, bool)` I don't see why one would want to return an `error`.

1_player|4 years ago

I don't understand your example, `isSet` is always true and can never be false. Missed something?

gnulinux|4 years ago

It works because it's false when uninitialized (as default value). So if not initialized it represents Nothing value. When it is initialized it's Just T.

hmmdar|4 years ago

The only time `IsSet` would be false is when `NewOption` was not used to initialize the value.

e.g.

  var o Option[int32]
or could have `None` helper

  func None[T any]() Option[T] { return Option[T]{} }

  o := None[int32]()